jwt --- JSON Web Token¶
面向 MicroPython 的 JSON Web Token(JWT)标准的小型实现。JWT 是一种紧凑的、URL 安全的容器,用于承载由签发者签名的 JSON 载荷,从而使验证者能够检测篡改和过期。
此 MicroPython 移植版本特意做得非常精简:
仅支持 HS256(使用 SHA-256 的 HMAC)。RSA / ECDSA / EdDSA 算法未实现;签发者和验证者必须共享一个对称密钥。
可选的
exp(过期)声明会被处理。其他注册声明(nbf、iat、iss、aud、sub、jti)会原样保留在载荷中传递,但不会被验证;应用程序如有需要可自行检查它们。不支持密钥轮换、JWKS 或受众列表处理。
函数¶
- jwt.encode(payload: dict, key: bytes | str, algorithm: str = 'HS256') str¶
将 payload 编码为一个已签名的 JWT,并返回所得的紧凑序列化结果(形如
"header.payload.signature"的str,每个段均经过 Base64-URL 编码)。- payload
一个可 JSON 序列化的声明字典。标准声明(
exp、iat、sub、...)会原样传递;允许使用自定义的应用程序键。- key
共享的 HMAC 密钥。首选
bytes;str会自动以 UTF-8 编码。- algorithm
必须为
"HS256"(默认值)。其他任何值都会引发exceptions.InvalidAlgorithmError。
- jwt.decode(token: str, key: bytes | str, algorithms: list = ['HS256']) dict¶
验证 token 的签名以及(如果存在)其
exp声明,并返回解码后的载荷字典。任何失败都会引发exceptions.PyJWTError的子类——调用方通常捕获该基类。- token
由
encode()(或任何兼容的签发者)生成的紧凑 JWT 字符串。- key
共享的 HMAC 密钥。必须与编码时使用的密钥相匹配。
- algorithms
调用方愿意接受的算法列表。其中必须包含
HS256,并且 token 头部的alg必须在该列表中。默认值为["HS256"]。
引发:
exceptions.InvalidAlgorithmError——HS256不在 algorithms 中,或者 token 头部的alg是HS256以外的任何值。exceptions.InvalidTokenError—— token 格式不正确(未拆分为三个 Base64-URL 段,或某个段无法解码 / 解析为 JSON)。exceptions.InvalidSignatureError—— 签名与基于头部和载荷重新计算出的 HMAC 不匹配。exceptions.ExpiredSignatureError—— 载荷包含一个exp声明,其值小于当前 Unix 时间。要使此检查有意义,必须设置摄像头的时钟;参见ntptime.settime()。
异常¶
所有异常都嵌套在模块属性 jwt.exceptions 之下。
- exception exceptions.PyJWTError¶
所有 JWT 失败的基类。如果你无需区分下面列出的各种情况,则捕获此类。
- exception exceptions.InvalidTokenError¶
token 在结构上无效——段的数量不对、某个段无法通过 Base64 解码,或 JSON 无法解析。是
exceptions.PyJWTError的子类。
- exception exceptions.InvalidAlgorithmError¶
token 的算法不在调用方接受的列表中,或者调用方请求了
HS256以外的算法。是exceptions.PyJWTError的子类。
- exception exceptions.InvalidSignatureError¶
token 的签名与使用所提供密钥根据头部和载荷计算出的 HMAC 不匹配。是
exceptions.PyJWTError的子类。
- exception exceptions.ExpiredSignatureError¶
token 的
exp声明已是过去时间。是exceptions.PyJWTError的子类。要使此检查有意义,必须设置摄像头的挂钟时间(通过ntptime.settime())。
示例¶
一个对称密钥的签发/验证流程:
import jwt
import time
SECRET = b"keep-this-out-of-source-control"
payload = {
"sub": "kitchen-cam",
"role": "admin",
"exp": time.time() + 3600, # 1 hour from now
}
token = jwt.encode(payload, SECRET)
print("token:", token)
try:
claims = jwt.decode(token, SECRET)
except jwt.exceptions.PyJWTError as e:
print("rejected:", type(e).__name__)
else:
print("subject:", claims["sub"])
签名和验证使用相同的密钥,因此验证者必须持有签发者所使用的密钥。对于摄像头作为签发者的服务(向配对的手机分发 token),请将密钥保存在摄像头文件系统中,并像对待任何其他长期凭据一样对待它——参见 运维:密钥、过期与故障排查。