3. JWT 令牌结构详解:Header、Payload、Signature 与算法选择

JWT(JSON Web Token)是 OAuth 2.0 授权流程中最常用的令牌格式。理解其内部结构是正确实现令牌校验、缓存与异步刷新的前提。本章将深入拆解 JWT 的三个组成部分,并对比两种核心签名算法 RS256 与 HS256 的工程选型差异。

3.1 JWT 三段式结构总览

一个完整的 JWT 由三个 Base64URL 编码的片段组成,以点号(.)分隔:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA...

三段分别对应:Header(头部)、Payload(载荷)、Signature(签名)。

JWT 三段式结构 Header(头部) 算法 & 令牌类型 {"alg":"RS256","typ":"JWT"} Base64URL 编码 Payload(载荷) 声明(Claims) sub, iss, exp, scope... Base64URL 编码 Signature(签名) 防篡改校验 HMAC / RSA 签名 Base64URL 编码 最终格式:Header.Payload.Signature(三段均由 Base64URL 编码,非加密)

3.2 Header(头部)

Header 通常包含两个关键字段:令牌类型(typ)和签名算法(alg)。

字段 含义 示例值
typ 令牌类型,固定为 JWT "JWT"
alg 签名算法,决定签名与校验方式 "RS256" 或 "HS256"
kid 密钥标识(可选),用于多密钥轮换场景 "key-id-1"
// 典型 Header 示例(RS256)
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "rsa-key-2024-01"
}
工程提示:在微服务网关中,务必先校验 alg 字段是否在白名单内,防止算法混淆攻击(如将 RS256 降级为 HS256)。

3.3 Payload(载荷)

Payload 包含 声明(Claims),分为三类:注册声明、公共声明、私有声明。

类别 常见声明 说明
注册声明 iss(签发者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(生效时间)、iat(签发时间)、jti(唯一标识) 建议始终包含 exp 和 jti,用于过期校验与重放攻击防护
公共声明 scope、client_id、roles 在 IANA JSON Web Token Claims 注册表中定义,或使用 URI 命名空间
私有声明 user_id、tenant_id、permissions 业务自定义字段,注意不要放入敏感信息(Payload 仅 Base64 编码,非加密)
// 典型 Payload 示例
{
  "iss": "https://auth.example.com",
  "sub": "user-12345",
  "aud": "api-gateway",
  "exp": 1735689600,
  "iat": 1735603200,
  "jti": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "scope": "openid profile email",
  "roles": ["admin", "editor"],
  "tenant_id": "tenant-001"
}
安全警告:Payload 中的任何数据都是可读的(Base64 解码即明文)。绝对不要在 Payload 中存放密码、密钥、身份证号等敏感信息。如需加密载荷,应使用 JWE(JSON Web Encryption)。

3.4 Signature(签名)

Signature 是对 Header 和 Payload 的完整性保护。生成公式如下:

Signature = HMAC_SHA256(
  base64urlEncode(header) + "." + base64urlEncode(payload),
  secret
)

或使用 RSA 私钥签名:

Signature = RSA_SHA256(
  base64urlEncode(header) + "." + base64urlEncode(payload),
  privateKey
)

校验方使用相同的密钥或公钥重新计算签名,比对是否一致。任何对 Header 或 Payload 的篡改都会导致签名校验失败。

3.5 RS256 vs HS256:算法选择对比

RS256(RSA + SHA-256)和 HS256(HMAC + SHA-256)是 JWT 最常用的两种签名算法。它们在密钥管理、性能、安全模型上有本质区别。

对比维度 RS256(非对称) HS256(对称)
密钥类型 私钥签名,公钥校验 单一共享密钥
密钥分发 公钥可公开,私钥仅签发方持有 所有校验方必须持有相同密钥
签名速度 较慢(RSA 运算) 极快(HMAC 运算)
校验速度 较快(公钥校验) 极快(HMAC 运算)
密钥轮换 支持,通过 kid 字段实现 困难,需同步所有服务
安全风险 私钥泄露风险,但公钥泄露不影响 共享密钥泄露后,攻击者可伪造任意令牌
适用场景 多服务间令牌校验、第三方集成、开放 API 单体应用、内部服务间通信(网络隔离)
RS256 vs HS256 工程选型对比 RS256(非对称) 授权服务器 私钥签名 资源服务器 公钥校验 JWT 优势:公钥可安全分发,私钥仅一处持有 适合:微服务网关、第三方 API 授权 注意:签名性能略低,需管理证书生命周期 建议使用 2048 位以上 RSA 密钥 HS256(对称) 授权服务器 共享密钥签名 资源服务器 相同密钥校验 JWT 优势:性能极高,实现简单 适合:单体应用、内部服务(网络隔离) 风险:密钥泄露可伪造任意令牌 密钥轮换需同步所有服务,运维复杂

3.6 工程选型建议

  • 优先选择 RS256:在微服务架构、API 网关、多客户端场景下,非对称算法使密钥管理更安全、更灵活。
  • HS256 仅限受控环境:当所有服务都在同一网络域且密钥分发可控时,HS256 的高性能优势才能发挥。
  • 避免算法降级攻击:校验时强制检查 alg 字段是否与预期一致,拒绝 "none" 算法。
  • 密钥轮换策略:使用 kid 字段标识密钥版本,支持平滑轮换而不中断服务。
实战要点:在 OAuth 2.0 授权码流程中,授权服务器签发 RS256 签名的 JWT,资源服务器通过从 /.well-known/jwks.json 端点获取公钥进行校验。这是目前业界最推荐的令牌校验架构。