2、JWT结构解析:Header、Payload、Signature的组成与作用
JWT(JSON Web Token)是一种紧凑的、URL安全的令牌表示方式,用于在各方之间以JSON对象的形式安全传输信息。一个标准的JWT由三个独立的部分组成,以点号(.)分隔:Header(头部)、Payload(载荷)、Signature(签名)。其典型结构如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
上述字符串中,第一部分是Base64URL编码后的Header,第二部分是Base64URL编码后的Payload,第三部分是使用指定算法和密钥生成的Signature。
2.1 Header(头部)
Header 是 JWT 的第一部分,通常包含两个关键字段:令牌类型(typ)和签名算法(alg)。它使用 Base64URL 编码,但请注意:Base64URL 编码不是加密,任何人都可以解码查看其内容。
| 字段 | 含义 | 示例值 | 说明 |
|---|---|---|---|
alg |
签名算法(Algorithm) | HS256、RS256、ES256 |
指定生成签名所使用的算法,是验证令牌完整性的核心 |
typ |
令牌类型(Type) | JWT |
声明该令牌为 JWT,帮助解析器识别 |
cty |
内容类型(Content Type) | JWT(可选) |
当 JWT 嵌套使用时,声明内部结构类型 |
常见算法对比:
- HS256(HMAC with SHA-256):对称加密,签名和验证使用同一个密钥。适合单一服务内部使用。
- RS256(RSA with SHA-256):非对称加密,使用私钥签名、公钥验证。适合微服务间或第三方认证。
- ES256(ECDSA with SHA-256):基于椭圆曲线的非对称算法,密钥更短,性能更高。
// 原始 Header JSON
{
"alg": "HS256",
"typ": "JWT"
}
// Base64URL 编码后
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
2.2 Payload(载荷)
Payload 是 JWT 的第二部分,包含实际要传递的声明(Claims)。声明是关于实体(通常是用户)和附加数据的陈述。Payload 同样使用 Base64URL 编码,不提供机密性保护,因此绝对不要在此存放密码、密钥等敏感信息。
声明分为三类:
| 类别 | 字段 | 全称 | 说明 |
|---|---|---|---|
| 注册声明 (Registered Claims) |
iss |
Issuer | 签发者,标识签发该 JWT 的实体 |
sub |
Subject | 主题,通常为用户的唯一标识 | |
aud |
Audience | 接收方,标识该 JWT 的目标受众 | |
exp |
Expiration Time | 过期时间,UNIX 时间戳,过期后令牌无效 | |
nbf |
Not Before | 生效时间,在此之前令牌不可用 | |
iat |
Issued At | 签发时间,UNIX 时间戳 | |
jti |
JWT ID | 令牌唯一标识,用于防止重放攻击 | |
| 公共声明 (Public Claims) |
自定义 | — | 在 IANA JSON Web Token Registry 中注册或使用防冲突命名空间(如 URL) |
| 私有声明 (Private Claims) |
自定义 | — | 双方约定使用的自定义字段,不注册,需避免命名冲突 |
// 原始 Payload JSON
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"role": "admin",
"permissions": ["read", "write", "delete"]
}
// Base64URL 编码后
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJyb2xlIjoiYWRtaW4iLCJwZXJtaXNzaW9ucyI6WyJyZWFkIiwid3JpdGUiLCJkZWxldGUiXX0
最佳实践:Payload 中只存放必要的最小信息,如用户 ID、角色、权限范围。避免存放完整的用户对象或敏感数据。对于需要保密的信息,应使用 JWE(JSON Web Encryption)进行加密。
2.3 Signature(签名)
Signature 是 JWT 的第三部分,用于验证令牌在传输过程中未被篡改,并确认发送者的身份。签名由以下三部分通过指定算法计算得出:
- 编码后的 Header
- 编码后的 Payload
- 一个密钥(Secret)
签名生成公式(以 HS256 为例):
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
验证过程:接收方使用相同的密钥和算法,对接收到的 Header 和 Payload 重新计算签名,然后与令牌中的签名进行比较。如果一致,则令牌未被篡改;否则令牌无效。
2.4 三部分协同工作
JWT 的三个部分各司其职,共同构建了一个安全、可验证的身份令牌:
- Header 告诉系统“用什么算法”来验证签名。
- Payload 告诉系统“谁在请求”以及“有什么权限”。
- Signature 确保 Header 和 Payload 没有被篡改,并且确实由可信的签发者生成。
安全警告:
- 永远不要在 JWT 的 Payload 中存储密码、密钥、信用卡号等敏感信息。
- 始终验证
alg字段,防止算法混淆攻击(攻击者将RS256改为HS256并使用公钥作为密钥验证)。 - 设置合理的
exp(过期时间),避免令牌长期有效。 - 使用 HTTPS 传输 JWT,防止中间人截获。
2.5 完整 JWT 示例
以下是一个包含三个部分的完整 JWT 令牌及其解码后的内容:
// 完整 JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJyb2xlIjoiYWRtaW4ifQ.tXU1VZq0X5Z0X5Z0X5Z0X5Z0X5Z0X5Z0X5Z0X5Z0
// 解码后的 Header
{
"alg": "HS256",
"typ": "JWT"
}
// 解码后的 Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"role": "admin"
}
// 签名(二进制,不可读)
[HMACSHA256 计算结果]