JWT 测试是什么
JWT 测试围绕「服务端是否严格校验」展开:签名算法校验(拒绝 none 与算法混淆)、exp 与 nbf 时间窗、aud 受众与 iss 签发者校验、密钥轮换兼容,以及错误令牌统一返回 401。核心认知是:payload 只是 Base64URL 编码,任何人可解码,不能当作可信数据。
基本信息
| 结构 | header.payload.signature 三段 Base64URL,用点连接 |
|---|---|
| 关键校验 | 签名算法、exp 过期、nbf 生效时间、aud 受众、iss 签发者 |
| 常见攻击面 | 算法替换为 none、RS 与 HS 算法混淆、篡改载荷不验签 |
| 边界用例 | 过期一秒、未来时间、跨服务复用、旧密钥签名 |
| 错误处理 | 无效令牌统一 401,不泄露校验失败细节 |
典型使用场景
- 登录签发链路:核对签发声明与服务端校验配置一致
- 权限边界:低权限令牌访问高权限接口必须被拒
- 密钥轮换:重叠期内旧令牌仍可用,伪造密钥的令牌不可用
- 篡改测试:改动载荷一个字符,签名校验必须失败
- 过期策略:过期令牌被拒且能正常走刷新流程
- 跨系统复用检查:A 系统令牌打到 B 系统应被拒绝
令牌边界用例(Python 示意)
令牌边界用例(Python 示意)
import time, jwt
# 过期令牌:exp 设为 60 秒前,服务端必须拒绝
expired = jwt.encode({"sub": "u1", "exp": int(time.time()) - 60}, "k", algorithm="HS256")
r = client.get("/me", headers={"Authorization": "Bearer " + expired})
assert r.status_code == 401
# 同类用例:nbf 设为未来时间、aud 指向其他服务、payload 篡改一个字符
# 算法用例:将 header 中 alg 改为 none 并去掉签名,必须同样返回 401校验项与对应用例
| 校验项 | 要求 | 用例断言 |
|---|---|---|
| 签名算法 | 拒绝 none,拒绝 HS 与 RS 混淆 | 篡改或换算法令牌返回 401 |
| exp | 过期即失效 | 过期一秒的令牌被拒 |
| nbf | 未生效令牌被拒 | 未来时间令牌被拒 |
| aud 与 iss | 受众与签发者匹配 | 跨服务令牌被拒 |
| 密钥轮换 | 重叠期新旧密钥均可验签 | 新密钥签发、旧密钥验证 |
只解码 payload 就当可信数据使用是常见缺陷:任何人都能构造合法 Base64 载荷,服务端必须完成签名与声明校验后再进入业务逻辑。
时间校验受服务器时钟影响:允许的时钟偏移(leeway)要显式配置并写进用例,否则偶发的无效令牌告警很难复现与解释。