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