JWT 令牌结构详解:Header、Payload 和 Signature
JWT 令牌结构详解
每个 JSON Web Token(JWT)都是一个紧凑、URL 安全的字符串,用于在双方之间传递声明。理解其内部结构对于任何从事基于令牌安全开发的开发者来说都是必不可少的。
JWT 的三个部分
一个 JWT 由三个用点号(.)分隔的部分组成:
header.payload.signature
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
每个部分都是经过 base64url 编码的 JSON。JWT 是签名而非加密的——任何人都可以解码并读取其内容。
第 1 部分:Header(头部)
header 包含关于令牌的元数据——签名算法和令牌类型。
| 字段 | 说明 | 示例值 |
|-------|-------------|----------------|
| alg | 签名算法(必填) | HS256, RS256, ES256 |
| typ | 令牌类型(可选) | JWT |
| kid | 密钥 ID(可选) | "key-1" |
{
"alg": "HS256",
"typ": "JWT"
}
alg 字段告诉验证方是哪个算法创建了签名。算法不匹配——或接受 alg: "none"——是常见的 JWT 安全漏洞。
第 2 部分:Payload(载荷)
payload 包含关于用户的声明和元数据。声明分为三类:
已注册声明(Registered Claims)
| 声明 | 全称 | 用途 |
|-------|-----------|---------|
| iss | Issuer | 令牌的签发者 |
| sub | Subject | 标识用户 |
| aud | Audience | 预期接收方 |
| exp | Expiration | 令牌过期时间戳 |
| nbf | Not Before | 令牌在该时间之前无效 |
| iat | Issued At | 令牌创建时间戳 |
| jti | JWT ID | 唯一令牌标识符 |
解码后的 Payload 示例
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622,
"iss": "https://auth.example.com"
}
公共声明在 IANA 注册表中定义,或使用具有防冲突能力的 URI。私有声明是签发方与使用方之间约定的自定义声明。
第 3 部分:Signature(签名)
签名是通过使用 header 中的算法,将编码后的 header、编码后的 payload 与一个密钥组合而生成的。它有两个用途:
- 完整性(Integrity)——确认令牌在签名后未被修改。
- 身份验证(Authentication)——证明令牌由预期的签发方签名。
HS256 签名创建
HMACSHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
secret
)
RS256 签名创建
RSASHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Base64url 与标准 Base64 的对比
| 方面 | 标准 Base64 | Base64url |
|--------|-----------------|-----------|
| 第 62 个字符 | + | - |
| 第 63 个字符 | / | _ |
| 填充 | = | 省略 |
这种编码方式确保 JWT 可以安全地用于 HTTP 头、查询参数和 URL 路径,而无需进行百分号编码。
完整的 JWT 创建流程
- 创建 header JSON 并进行 base64url 编码。
- 创建 payload JSON 并进行 base64url 编码。
- 使用
.分隔符拼接。 - 使用所选算法和密钥进行签名。
- 对签名进行 base64url 编码。
- 使用
.分隔符拼接所有三个部分。
安全注意事项
- 切勿在 payload 中存储密钥。 payload 是编码的,而非加密的。
- 始终验证签名。 如果没有验证,任何人都可以伪造令牌。
- 检查
algheader。 拒绝alg: "none"和算法降级尝试。 - 设置较短的过期时间。 使用
exp声明,时间设为分钟或小时,而非月。
在线解码 JWT 令牌
使用 JWT 解码器工具来检查任何令牌。粘贴后即可立即看到解码后的 header、payload 和签名算法。所有处理都在您的浏览器中完成。