2、JWT结构解析:Header头部、Payload载荷、Signature签名的组成与作用
JWT(JSON Web Token)是一种紧凑的、URL安全的令牌表示方式,其核心结构由三个独立的部分通过点号(.)连接而成。理解这三部分的组成与作用,是进行JWT契约校验的基础。
JWT标准结构示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
上述令牌由三个Base64URL编码的字符串组成,分别对应Header、Payload和Signature。
2.1 Header(头部)—— 算法与类型声明
Header是JWT的第一段,通常包含两个关键字段:令牌类型(typ)和签名算法(alg)。它告诉接收方如何解析和验证这个令牌。
| 字段 | 含义 | 常见值 | 说明 |
|---|---|---|---|
| alg | 签名算法(Algorithm) | HS256、RS256、ES256 | 必填字段,指定用于生成签名的算法 |
| typ | 令牌类型(Type) | JWT | 可选字段,通常固定为"JWT" |
| cty | 内容类型(Content Type) | JWT | 可选字段,用于嵌套签名或加密场景 |
安全提示:alg字段是JWT安全的关键。服务端在校验时必须严格限制允许的算法列表,防止攻击者将"RS256"篡改为"none"或对称算法"HS256"来绕过签名验证。
// 典型的JWT Header示例
{
"alg": "HS256", // 使用HMAC-SHA256对称签名算法
"typ": "JWT" // 声明这是一个JWT令牌
}
2.2 Payload(载荷)—— 声明数据的载体
Payload是JWT的第二段,包含实际传递的声明(Claims)。声明是关于实体(通常是用户)和附加元数据的陈述。JWT规范定义了三种类型的声明:注册声明、公共声明和私有声明。
2.2.1 注册声明(Registered Claims)
这些是预定义的、非强制性的但推荐使用的声明,提供一组有用的、可互操作的声明名称。
| 声明名 | 全称 | 说明 | 校验要点 |
|---|---|---|---|
| iss | Issuer | 签发者,标识签发JWT的主体 | 验证是否与预期签发者匹配 |
| sub | Subject | 主题,标识JWT所面向的用户 | 通常为用户的唯一标识 |
| aud | Audience | 接收方,标识JWT的预期接收者 | 验证当前服务是否在aud列表中 |
| exp | Expiration Time | 过期时间,UNIX时间戳格式 | 必须校验当前时间是否已超过exp |
| nbf | Not Before | 生效时间,在此之前JWT不可用 | 当前时间必须晚于nbf |
| iat | Issued At | 签发时间,UNIX时间戳格式 | 可用于判断令牌是否过于陈旧 |
| jti | JWT ID | 唯一标识符,防止重放攻击 | 服务端需维护已使用的jti列表 |
2.2.2 公共声明与私有声明
- 公共声明(Public Claims):在IANA JSON Web Token Claims注册表中定义的声明,或使用URI(统一资源标识符)作为名称以避免冲突。
- 私有声明(Private Claims):由JWT的生产者和消费者之间协商的自定义声明,如角色、权限、用户昵称等业务数据。
// 一个包含多种声明的Payload示例
{
"iss": "https://auth.example.com", // 注册声明:签发者
"sub": "user_123456", // 注册声明:用户ID
"aud": ["api.example.com"], // 注册声明:接收方
"exp": 1735689600, // 注册声明:过期时间
"iat": 1735603200, // 注册声明:签发时间
"role": "admin", // 私有声明:用户角色
"permissions": ["read", "write"] // 私有声明:权限列表
}
重要提醒:Payload仅经过Base64URL编码,并未加密。任何持有令牌的人都可以解码并读取其中的内容。切勿在Payload中存放密码、密钥、信用卡号等敏感信息。如需保护数据内容,应使用JWE(JSON Web Encryption)。
2.3 Signature(签名)—— 完整性与真实性的保障
Signature是JWT的第三段,通过对Header和Payload进行签名生成,用于验证令牌在传输过程中未被篡改,并确认其确实由预期的签发者生成。
签名的生成过程如下:
- 将Header和Payload分别进行Base64URL编码。
- 将编码后的Header和Payload用点号(.)连接,形成签名输入字符串。
- 使用Header中指定的算法(alg)和密钥(secret或私钥)对输入字符串进行签名。
- 将生成的签名进行Base64URL编码,作为JWT的第三段。
// 签名生成伪代码(以HMAC-SHA256为例)
signature = HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
2.4 三段结构的协同作用
JWT的三段结构各自承担不同职责,共同保障令牌的安全传输:
| 组成部分 | 核心职责 | 是否加密 | 是否可篡改 | 校验重点 |
|---|---|---|---|---|
| Header | 声明解析方式与算法 | 否(仅编码) | 可篡改,但会被签名检测 | 验证alg是否在白名单内 |
| Payload | 承载业务数据与元数据 | 否(仅编码) | 可篡改,但会被签名检测 | 验证exp、nbf、aud等声明 |
| Signature | 保证完整性与真实性 | 是(签名不可逆) | 不可篡改(无密钥无法伪造) | 重新计算签名并比对 |
核心结论:JWT的安全性建立在Signature之上。Header和Payload虽然可读,但任何修改都会导致签名验证失败。在契约校验中,签名验证是第一步,也是最重要的一步——只有通过签名验证的令牌,才值得进一步检查Payload中的声明内容。