2. JWT 结构解析
JSON Web Token(JWT)由三个独立的部分组成,通过 .(点号)连接,形成紧凑的字符串。理解每一部分的构成与编码原理,是构建安全鉴权体系的基础。
JWT 典型结构示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
三部分依次为:Header(头部)、Payload(载荷)、Signature(签名)。
2.1 Header 头部结构
Header 通常包含两个关键字段:令牌类型(typ)和签名算法(alg)。
| 字段 | 含义 | 常见值 | 说明 |
|---|---|---|---|
typ |
令牌类型 | JWT |
固定为 JWT,表示这是一个 JSON Web Token |
alg |
签名算法 | HS256 / RS256 / ES256 |
指定用于生成签名的算法,不可缺失 |
kid |
密钥标识 | 字符串 | 可选字段,用于多密钥场景下选择对应密钥 |
安全提示: 服务端在验证 JWT 时,必须校验
alg 字段是否与预期算法一致。攻击者可能将 RS256 篡改为 none 或 HS256,绕过签名验证(即“算法混淆攻击”)。
// 原始 Header JSON
{
"alg": "HS256",
"typ": "JWT"
}
// 经过 Base64URL 编码后的字符串
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
2.2 Payload 载荷结构
Payload 是 JWT 的核心数据载体,包含声明(Claims)。声明分为三类:注册声明、公共声明、私有声明。
| 类别 | 字段 | 含义 | 是否必须 |
|---|---|---|---|
| 注册声明 (Registered Claims) |
iss |
签发者(Issuer) | 推荐 |
sub |
主题(Subject),通常为用户 ID | 推荐 | |
exp |
过期时间(Expiration Time) | 必须 | |
iat |
签发时间(Issued At) | 推荐 | |
| 公共声明 (Public Claims) |
https://example.com/role |
自定义 URI 命名空间下的声明 | 可选 |
| 私有声明 (Private Claims) |
role / permissions |
服务双方约定的自定义字段 | 可选 |
重要安全原则: Payload 仅经过 Base64URL 编码,并未加密。任何持有 JWT 的人都可以解码读取其中的数据。切勿在 Payload 中存放密码、密钥、身份证号等敏感信息。
// 原始 Payload JSON
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622,
"role": "admin"
}
// 经过 Base64URL 编码后的字符串
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDI2MjIsInJvbGUiOiJhZG1pbiJ9
2.3 Signature 签名结构
Signature 用于验证 JWT 的完整性和真实性,防止数据被篡改。其生成过程如下:
- 将 Header 和 Payload 分别进行 Base64URL 编码。
- 将编码后的字符串用 . 连接。
- 使用 Header 中指定的算法和密钥,对连接后的字符串进行签名。
// 签名生成伪代码
signature = HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
| 算法 | 类型 | 密钥 | 适用场景 |
|---|---|---|---|
HS256 |
对称 | 单一共享密钥 | 单体服务、内部信任环境 |
RS256 |
非对称 | 私钥签名 / 公钥验证 | 分布式系统、微服务、第三方认证 |
ES256 |
非对称(椭圆曲线) | 私钥签名 / 公钥验证 | 性能敏感、移动端、IoT 设备 |
分布式系统推荐: 在微服务架构中,优先使用
RS256 或 ES256。认证中心持有私钥签发 JWT,各业务服务只需持有公钥即可验证签名,无需共享密钥,降低密钥泄露风险。
2.4 Base64URL 编码原理
JWT 使用 Base64URL 而非标准 Base64 编码,主要为了解决 URL 传输中的兼容性问题。
| 对比项 | 标准 Base64 | Base64URL |
|---|---|---|
| 第 62 位字符 | + |
-(减号) |
| 第 63 位字符 | / |
_(下划线) |
| 填充字符 | = |
去除(不填充) |
| URL 安全性 | 需额外 URL 编码 | 直接可用,无需转义 |
编码步骤:
- 对原始 JSON 字符串进行标准 Base64 编码。
- 将
+替换为-,将/替换为_。 - 去除末尾的
=填充字符。
// 标准 Base64 编码结果(含填充)
dGhpcyBpcyBhIHRlc3Q=
// Base64URL 编码结果(替换 + 和 /,去除 =)
dGhpcyBpcyBhIHRlc3Q
解码注意事项: 解码时需先补回
= 填充(使长度变为 4 的倍数),再将 - 替换回 +、_ 替换回 /,然后进行标准 Base64 解码。忽略填充补全可能导致解码失败或数据损坏。