2. JWT 结构详解:Header、Payload、Signature 的组成与作用
JSON Web Token(JWT)是一种紧凑的、URL 安全的令牌表示方式,用于在各方之间以 JSON 对象的形式安全地传输信息。一个标准的 JWT 由三个独立的部分组成,它们通过点号(.)连接,形成如下格式:
xxxxx.yyyyy.zzzzz
这三部分分别对应 Header(头部)、Payload(载荷) 和 Signature(签名)。每一部分都经过 Base64URL 编码,确保在 HTTP 头或 URL 参数中传输时不会产生歧义。
关键认知:JWT 的每一部分都是独立编码的,但只有 Signature 部分能保证令牌的完整性和真实性。Header 和 Payload 仅经过编码(非加密),因此不应在其中存放敏感信息(如密码、信用卡号)。
2.1 Header(头部)
Header 是 JWT 的第一部分,通常包含两个主要字段:令牌类型(typ)和签名算法(alg)。它描述了如何对 JWT 进行签名或加密处理。
| 字段 | 含义 | 示例值 | 说明 |
|---|---|---|---|
alg |
签名算法 | HS256 / RS256 |
必填。指定生成 Signature 的算法。HS256 为对称 HMAC-SHA256,RS256 为非对称 RSA-SHA256。 |
typ |
令牌类型 | JWT |
可选。通常固定为 JWT,表示这是一个 JWT 令牌。 |
kid |
密钥 ID | key-abc-123 |
可选。当使用多组密钥时,用于标识具体使用哪一组密钥进行验证。 |
一个典型的 Header JSON 对象如下:
{
"alg": "HS256",
"typ": "JWT"
}
该 JSON 经过 Base64URL 编码后,形成 JWT 的第一段字符串。
安全警告:切勿使用
alg: "none"。某些旧版 JWT 库允许将算法设为 none 以跳过签名验证,这会导致严重的安全漏洞,攻击者可以伪造任意令牌。生产环境中必须禁用 none 算法。
2.2 Payload(载荷)
Payload 是 JWT 的第二部分,包含实际要传递的声明(Claims)。声明是关于实体(通常是用户)和附加数据的陈述。JWT 规范定义了三种类型的声明:注册声明、公共声明 和 私有声明。
| 类型 | 说明 | 常见字段 |
|---|---|---|
| 注册声明 | 预定义的一组非强制性但推荐的声明,提供互操作性。 | iss(签发者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(生效时间)、iat(签发时间)、jti(JWT ID) |
| 公共声明 | 由使用 JWT 的各方自行定义,为避免冲突,建议在 IANA JSON Web Token Claims 注册表中注册,或使用命名空间 URI。 | name、preferred_username |
| 私有声明 | 在同意使用 JWT 的各方之间共享的自定义声明,不属于注册或公共声明。 | user_id、role、permissions |
一个典型的 Payload JSON 对象示例:
{
"sub": "1234567890",
"name": "张三",
"iat": 1516239022,
"exp": 1516242622,
"role": "admin",
"permissions": ["read:users", "write:users"]
}
最佳实践:Payload 中只存放必要的最小声明集。避免存放敏感数据,因为 Payload 仅经过 Base64URL 编码,任何人都可以解码读取。对于需要保密的信息,应使用 JWE(JSON Web Encryption)进行加密。
2.3 Signature(签名)
Signature 是 JWT 的第三部分,用于验证消息在传输过程中未被篡改,并确认消息的发送方身份。签名的生成过程依赖于 Header 中指定的算法和一个密钥(或密钥对)。
签名生成的基本公式如下:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
具体步骤:
- 将 Header 和 Payload 分别进行 Base64URL 编码。
- 将编码后的 Header 和 Payload 用点号(.)连接起来。
- 使用 Header 中指定的算法(如 HMAC-SHA256)和密钥对上述字符串进行签名。
- 将生成的签名进行 Base64URL 编码,得到 Signature 部分。
验证方收到 JWT 后,使用相同的算法和密钥重新计算签名,并与 JWT 中的 Signature 进行比较。如果一致,则证明令牌未被篡改且来源可信。
2.4 三部分协同工作
JWT 的三个部分各司其职,共同构建了一个安全、自包含的令牌系统:
- Header 告诉验证方“我是如何被签名的”,确保双方使用相同的算法规则。
- Payload 携带业务数据,如用户 ID、角色、过期时间等,使令牌具有自描述能力。
- Signature 提供完整性保护和身份认证,防止数据被篡改,并确保令牌来自持有密钥的合法签发方。
在分布式系统中,这种结构使得服务无需查询中心化的会话存储,仅通过验证 JWT 签名即可确认用户身份和权限,从而实现无状态鉴权。
核心结论:JWT 的结构设计体现了“信任但验证”的安全原则。Header 和 Payload 是公开可读的,但 Signature 确保了它们的完整性和真实性。在分布式鉴权场景中,正确实现签名验证是保障系统安全的第一道防线。