3. JWT 数据结构详解

JWT(JSON Web Token)本质上是一个紧凑的、URL 安全的令牌表示方式,用于在各方之间以 JSON 对象的形式安全地传输信息。一个标准的 JWT 由三个独立的部分组成,以点号(.)分隔:Header、Payload、Signature。其结构表现为:xxxxx.yyyyy.zzzzz。

核心记忆点:JWT 的每一部分都是 Base64URL 编码后的 JSON 字符串。Base64URL 编码是标准 Base64 的变体,将 + 替换为 -,将 / 替换为 _,并去除末尾的 =,使其能够安全地放在 URL 中传输。
JWT 三段式结构总览 JWT 三段式结构总览 Header 算法声明 & 类型 Payload 声明(Claims) Signature 防篡改签名 最终格式:Base64URL(Header).Base64URL(Payload).Base64URL(Signature)

3.1 Header(头部)

Header 通常由两部分组成:令牌的类型(typ)和使用的签名算法(alg)。它是 JWT 的第一段,用于描述 JWT 的元数据。

声明字段 含义 是否必选 示例值
alg 签名算法,如 HMAC SHA256、RSA 等 是 "HS256"
typ 令牌类型,固定为 "JWT" 否(建议携带) "JWT"
cty 内容类型,用于嵌套 JWT 场景 否 "JWT"
安全提示:在生产环境中,务必在服务端白名单中校验 alg 字段。攻击者可能将 alg 改为 "none" 来绕过签名验证,导致严重的安全漏洞。
// 一个典型的 Header 示例
{
  "alg": "HS256",
  "typ": "JWT"
}
// 经过 Base64URL 编码后变为:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

3.2 Payload(载荷)

Payload 是 JWT 的第二部分,包含实际的声明(Claims)。声明是关于实体(通常是用户)和附加数据的陈述。JWT 规范定义了三种类型的声明:注册声明、公共声明和私有声明。

3.2.1 注册声明(Registered Claims)

这些是一组预定义的、非强制性的但推荐使用的声明,旨在提供一组有用的、可互操作的声明。

声明 全称 含义 类型
iss Issuer 签发者,标识签发 JWT 的主体 字符串或 URI
sub Subject 主题,标识 JWT 所面向的用户(通常是用户 ID) 字符串
aud Audience 接收方,标识此 JWT 的预期接收者 字符串或数组
exp Expiration Time 过期时间,必须晚于当前时间 NumericDate(秒)
nbf Not Before 生效时间,在此时间之前 JWT 不可用 NumericDate(秒)
iat Issued At 签发时间 NumericDate(秒)
jti JWT ID 唯一标识符,用于防止重放攻击 字符串
关键校验点:服务端在验证 JWT 时,必须严格校验 exp(过期时间)和 nbf(生效时间)。如果当前时间不在 [nbf, exp] 区间内,应直接拒绝该令牌。同时,建议校验 iss 和 aud 是否与预期值匹配。

3.2.2 公共声明与私有声明

  • 公共声明(Public Claims):可以在 IANA JSON Web Token Registry 中注册,或使用包含冲突避免命名空间的 URI 来定义。
  • 私有声明(Private Claims):由使用 JWT 的双方协商定义,不属于注册声明或公共声明。例如:"role": "admin"、"permissions": ["read", "write"]。
// 一个包含注册声明和私有声明的 Payload 示例
{
  "iss": "https://auth.example.com",
  "sub": "user_123456",
  "aud": "https://api.example.com",
  "exp": 1735689600,
  "iat": 1735603200,
  "jti": "unique-token-id-abc123",
  "role": "admin",
  "department": "engineering"
}
// 经过 Base64URL 编码后变为:eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMzQ1NiIsImF1ZCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tIiwiZXhwIjoxNzM1Njg5NjAwLCJpYXQiOjE3MzU2MDMyMDAsImp0aSI6InVuaXF1ZS10b2tlbi1pZC1hYmMxMjMiLCJyb2xlIjoiYWRtaW4iLCJkZXBhcnRtZW50IjoiZW5naW5lZXJpbmcifQ

3.3 Signature(签名)

Signature 是 JWT 的第三部分,用于验证消息在传输过程中未被篡改。对于使用私钥签名的令牌,它还可以验证 JWT 的发送方是否为它所声称的实体。

3.3.1 签名生成公式

签名是通过对编码后的 Header 和 Payload 进行组合,并使用指定的算法和密钥进行加密计算得出的。

// 通用签名生成公式
signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

// 对于非对称算法(如 RS256)
signature = RSASHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  privateKey
)

3.3.2 签名验证流程

  1. 接收方从 JWT 中提取出 Header 和 Payload 的 Base64URL 编码部分。
  2. 使用相同的算法和密钥(或公钥)对 header.payload 重新计算签名。
  3. 将计算出的签名与 JWT 中携带的签名进行比较。
  4. 如果两者完全一致,则说明 JWT 内容未被篡改;否则,拒绝该令牌。
JWT 签名生成与验证流程 JWT 签名生成与验证流程 签名生成(服务端) Base64URL(Header) Base64URL(Payload) 拼接:Header.Payload 算法 + Secret 签名 输出 Signature 签名验证(服务端) 提取 Header.Payload 相同算法 + Secret 计算新签名 比对两个签名

3.4 完整 JWT 示例

将上述三个部分通过点号连接,即构成一个完整的 JWT 令牌。

// 完整 JWT 示例
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzEyMzQ1NiIsImF1ZCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tIiwiZXhwIjoxNzM1Njg5NjAwLCJpYXQiOjE3MzU2MDMyMDAsImp0aSI6InVuaXF1ZS10b2tlbi1pZC1hYmMxMjMiLCJyb2xlIjoiYWRtaW4iLCJkZXBhcnRtZW50IjoiZW5naW5lZXJpbmcifQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
重要提醒:JWT 的 Header 和 Payload 仅经过 Base64URL 编码,并未加密。任何持有 JWT 的人都可以解码并查看其内容。因此,切勿在 Payload 中存放密码、密钥等敏感信息。如果需要保护内容,应使用 JWE(JSON Web Encryption)对 Payload 进行加密。

3.5 常见算法对比

算法 类型 密钥 性能 适用场景
HS256 对称(HMAC) 共享密钥 高 单一服务内部,或完全信任的微服务间
RS256 非对称(RSA) 私钥签名 / 公钥验证 中 分布式系统、第三方应用、开放 API
ES256 非对称(ECDSA) 私钥签名 / 公钥验证 高(密钥更短) 移动端、IoT 设备、对性能要求高的场景
选型建议:在分布式鉴权系统中,推荐使用非对称算法(如 RS256 或 ES256)。认证服务持有私钥签发令牌,其他业务服务仅需持有公钥即可验证令牌,无需共享密钥,大大降低了密钥泄露的风险。