首页/安全/等保与合规速查/JWT 认证安全:算法、校验与密钥轮换
密码与认证合规50 条

JWT 认证安全:算法、校验与密钥轮换

JWT 用于接口与服务间认证时应固定可信算法、完整校验声明(iss/aud/exp),并使用 JWKS 轮换密钥;仅签名不含加密,禁止将敏感数据放入载荷。

等保与合规速查安全更新于 2026-10-13

JWT 的安全边界

JWT(RFC 7519)是接口与服务间常用的认证载体。它只做签名,不做加密:载荷是 Base64URL 编码而非密文,任何人都能解出内容,因此手机号、身份证号这类信息不应放进载荷。常见的实现错误集中在三处:服务端信任令牌头里声明的算法、HS 与 RS 算法混淆、密钥长期不轮换。这三类问题的共同点是攻击者能借此伪造令牌。

基本信息

规范RFC 7519;密钥分发常配合 JWKS
推荐算法RS256 / ES256 等非对称算法,服务端白名单固定
必须校验签名、iss、aud、exp,必要时校验 nbf 与 jti
密钥管理用 JWKS 配合 kid 支持轮换,避免硬编码密钥
载荷原则只放非敏感声明,敏感数据由服务端查询获取

典型使用场景

  • 前后端分离:接口用 JWT 承载会话,需限制有效期
  • 服务间调用:内部服务用 JWT 做身份传递与授权
  • 开放平台:第三方接入用非对称签名验签,公钥通过 JWKS 分发
  • 单点登录联动:id_token 与访问令牌的校验逻辑需要区分
  • 安全测试:把算法与声明校验作为固定测试项

PyJWT 校验示例

PyJWT 校验示例
import jwt
# 固定算法白名单,禁止接受客户端指定的算法
payload = jwt.decode(
    token, key=public_key_pem,
    algorithms=["RS256"],
    audience="api.example.com", issuer="https://idp.example.com",
    options={"require": ["exp", "iss", "aud"]})
# 密钥轮换:用 JWKS 客户端按 kid 自动取公钥
from jwt import PyJWKClient
signing_key = PyJWKClient("https://idp.example.com/.well-known/jwks.json").get_signing_key_from_jwt(token)

风险与缓解

风险说明缓解
alg=none伪造无签名令牌服务端固定算法白名单
HS/RS 混淆用公钥当 HMAC 密钥伪造签名按密钥类型限定算法族
密钥不轮换泄露后影响面长期存在JWKS + kid 支持平滑轮换
载荷含敏感信息Base64 可解出明文载荷不放敏感数据,改用服务端查询
历史漏洞多与「信任 alg 头」有关:务必在服务端白名单校验算法,不接受客户端指定算法,也不要因为旧客户端兼容而放宽。
令牌有效期与吊销要一起设计:短有效期加刷新令牌是常见做法,服务端吊销名单或版本号可用于强制下线。

易错点

  • alg=none 或 HS/RS 混淆:属于高风险实现错误,可能导致令牌可被任意伪造
  • 把手机号等敏感信息写进载荷:载荷可被 Base64 解码,等同于明文传播
  • 只验签名不验 aud 与 iss:其他系统签发的令牌可能被错误接受
  • 密钥硬编码在配置里且不轮换:泄露后影响面难以收敛,且难以排查泄漏范围

数据来源与参考

  • RFC 7519(JWT)
  • OWASP JWT Cheat Sheet
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌