什么是 JWT?

JWT(JSON Web Token,RFC 7519)是一种开放标准,用于在各方之间以 JSON 对象的形式安全地传输信息。JWT 通常用于身份认证和信息交换场景。

JWT 的结构

一个 JWT 由三部分组成,用点号(.)分隔:

Header.Payload.Signature

1. Header(头部)

Header 通常包含两部分信息:

  • alg:签名算法,如 HS256RS256ES256
  • typ:令牌类型,固定为 JWT

示例:

{"alg": "RS256", "typ": "JWT"}

2. Payload(载荷)

Payload 包含声明(Claims),即要传输的数据。声明分为三类:

  • 注册声明(Registered Claims):预定义的标准字段

    • sub(Subject):主体,通常为用户 ID
    • iss(Issuer):签发者
    • exp(Expiration Time):过期时间
    • iat(Issued At):签发时间
    • aud(Audience):受众
    • nbf(Not Before):生效时间
  • 公共声明(Public Claims):自定义字段,需在 IANA 注册或使用命名空间避免冲突

  • 私有声明(Private Claims):双方约定的自定义字段

3. Signature(签名)

签名用于验证消息在传输过程中未被篡改。对于 HS256 算法,签名计算公式为:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

重要安全提示

JWT 的 Payload 是 Base64 编码而非加密,内容是明文可读的! 切勿在 JWT 中存放密码、信用卡号等敏感信息。

签名算法选择

对称算法(HS256/HS384/HS512)

  • 使用同一个密钥进行签名和验证
  • 适合单一服务端应用
  • 密钥必须严格保密

非对称算法(RS256/ES256)— 推荐

  • 使用私钥签名,公钥验证
  • 适合微服务/分布式系统
  • 公钥可以安全分发
  • 推荐 RS256 或 ES256

JWT 验证要点

必须验证的字段

  1. 签名验证:使用公钥或共享密钥验证签名
  2. exp(过期时间):拒绝过期的 token
  3. nbf(生效时间):拒绝尚未生效的 token
  4. iss(签发者):验证签发者是否可信
  5. aud(受众):验证 token 是否为本服务签发

常见安全风险

  • alg=none 攻击:服务端必须拒绝 alg: "none" 的 token
  • 密钥混淆攻击:验证算法必须与预期一致,防止 HS256 token 使用 RSA 公钥作为密钥
  • Token 泄露:不要在 URL 参数中传递 JWT,使用 Authorization: Bearer <token> 头部

Token 生命周期管理

推荐方案

  • Access Token:有效期 15-60 分钟
  • Refresh Token:有效期 7-30 天,支持轮换(Rotation)
  • 使用 Redis 维护黑名单用于紧急吊销
  • 短有效期 + Refresh Token 轮换是最佳实践

推荐 JWT 库

语言 推荐库
Node.js jsonwebtoken, jose
Python PyJWT, python-jose
Java jjwt, nimbus-jose-jwt
Go golang-jwt/jwt, lestrrat-go/jwx