JWT 是什么
JWT(JSON Web Token)是把声明信息编码成自包含令牌的格式,由头部、载荷、签名三段用点号连接,服务端只靠签名就能验证令牌是否由自己签发,不需要查询会话存储。它便于无状态扩容与跨系统传递身份,代价是「撤销」变得困难:签发出去的令牌在过期前一直有效,所以有效期管理与密钥管理比格式本身更关键。常见的风险集中在算法可被替换、密钥强度不足或泄露、有效期过长与载荷里放了不该放的内容。
基本信息
| 结构 | 头部.载荷.签名,三段 Base64URL 编码后以点号连接 |
|---|---|
| 签名算法 | 对称 HS256/HS512,非对称 RS256/ES256 |
| 载荷性质 | Base64URL 编码,可被任何人解码,不是加密 |
| 主要风险 | 算法可伪造、密钥弱或泄露、有效期过长、无法撤销 |
| 适用场景 | 服务间调用、短期访问令牌、跨系统身份传递 |
| 不适用场景 | 需要即时吊销的长效会话凭据 |
典型使用场景
- 前后端分离的接口鉴权:前端携带访问令牌调用后端接口
- 微服务间调用:服务用短期令牌传递调用者身份与权限范围
- 第三方授权:授权服务器下发访问令牌供资源服务校验
- 短期临时凭据:文件上传、下载链接等带有效期的访问凭证
- 移动端会话:配合刷新令牌控制访问令牌有效期
- 跨系统单点访问:在多个内部系统间传递身份而不共享会话存储
校验与使用要点
校验与使用要点
1. 服务端显式指定允许算法(不信任头部 alg 字段)
2. 使用强密钥(HS256 至少 256 位随机)或非对称(RS256/ES256)
3. 完整校验 iss/aud/exp/nbf 声明
4. 有效期短(分钟到小时级),刷新令牌单独管理并支持撤销
5. 不在 JWT 承载敏感明文(payload 是 Base64 编码,不是加密)
6. 令牌校验通过后仍要按资源做权限判断,声明中的角色不可全信常见配置错误示例
常见配置错误示例
错误:jwt.decode(token, verify=False) 或允许 alg=none
错误:接受 alg=HS256 但用公钥内容当对称密钥校验
正确:jwt.decode(token, key, algorithms=['RS256']) # 显式算法白名单
正确:使用库提供的密钥集合接口并校验 kid 与签发者
# 校验失败要返回统一错误,不要向客户端暴露具体原因风险与对策
| 风险 | 成因 | 对策 |
|---|---|---|
| 算法替换 | 信任头部 alg,允许 none 或对称算法混淆 | 服务端固定算法白名单 |
| 密钥泄露 | 硬编码、与前端共用、仓库提交 | 密钥托管与轮换,按环境隔离 |
| 无法撤销 | 无状态设计缺少黑名单机制 | 缩短有效期,维护吊销列表与版本号 |
| 载荷泄露 | 把敏感数据放进载荷 | 载荷只放标识与权限范围等非敏感信息 |
| 重放利用 | 缺少 jti 与一次性约束 | 关键操作叠加 jti 校验与防重放机制 |
签名密钥若被硬编码进前端项目等于公开:签发与校验所用密钥只存在于服务端。
需要即时失效能力时,常见做法是给令牌加版本号或用中央吊销列表,校验时比对该值;这会把部分状态带回服务端,属于用复杂度换可控性的取舍。