3. JWT 头部详解:typ 与 alg 声明

JWT 头部(Header)是令牌的第一段,通常由两个核心字段组成:typ(类型声明)和 alg(签名算法声明)。头部以 JSON 对象形式存在,经过 Base64URL 编码后成为令牌的第一部分。理解头部结构是正确解析和验证 JWT 的前提。

3.1 typ 类型声明

typ(Type)字段用于声明令牌的媒体类型,帮助解析方识别这是一个 JWT。虽然该字段在大多数实现中是可选的,但遵循规范可以增强互操作性。

字段 说明 典型值 是否必需
typ 令牌类型标识 "JWT" 推荐
cty 内容类型(嵌套 JWT 时使用) "JWT" 仅嵌套时
最佳实践:始终在头部中包含 "typ": "JWT"。这可以防止令牌类型混淆攻击,并确保接收方明确知道正在处理的是 JWT 而非其他格式的令牌。

3.2 alg 签名算法声明

alg(Algorithm)字段是头部中最关键的字段,它指定了用于签名或加密的算法。接收方必须根据此字段的值选择对应的验证逻辑。算法选择直接影响令牌的安全性。

3.3 常见算法类型:HS256 与 RS256

在实际生产环境中,HS256 和 RS256 是最广泛使用的两种签名算法。它们分别属于对称加密和非对称加密体系,在密钥管理、安全性和性能方面存在显著差异。

对比维度 HS256(HMAC-SHA256) RS256(RSA-SHA256)
加密类型 对称加密 非对称加密
密钥 单一共享密钥 私钥签名 / 公钥验证
密钥分发 需安全通道共享密钥 公钥可公开分发
性能 签名与验证均快 签名慢,验证快
适用场景 单一服务内部、信任边界明确 微服务间、第三方集成、开放 API
安全风险 密钥泄露可伪造任意令牌 私钥泄露风险,公钥泄露不影响
安全警告:切勿在头部中接受 "alg": "none"。攻击者可能篡改头部将算法改为 none,从而绕过签名验证。生产环境必须白名单允许的算法列表,并拒绝未知或未签名的令牌。

3.4 头部结构示例

以下是一个典型的 HS256 头部 JSON 对象及其 Base64URL 编码后的结果:

// 原始头部 JSON
{
  "typ": "JWT",
  "alg": "HS256"
}

// Base64URL 编码后(实际令牌第一部分)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

对于 RS256,头部结构完全相同,仅 alg 字段值不同:

{
  "typ": "JWT",
  "alg": "RS256"
}

3.5 算法选择决策流程

下图展示了在系统设计阶段如何根据场景选择合适的签名算法:

JWT 签名算法选择决策流程 选择签名算法 单一服务 内部使用? 是 否 HS256(对称密钥) RS256(非对称密钥) 密钥需安全共享 适合内部服务间通信 公钥可公开,私钥保密 适合跨服务、第三方集成

3.6 头部常见安全陷阱

  • 算法混淆攻击:攻击者将 alg 从 RS256 改为 HS256,并利用泄露的公钥作为 HMAC 密钥进行签名。防御措施:验证时强制绑定算法与密钥类型。
  • 空算法攻击:将 alg 改为 none 绕过签名验证。防御措施:拒绝 none 算法,白名单允许的算法列表。
  • 算法降级:将强算法降级为弱算法。防御措施:服务端固定期望的算法,不信任客户端声明的算法。
核心要点:头部中的 alg 字段是 JWT 安全的第一道防线。永远不要信任客户端提供的算法声明,服务端应预先配置允许的算法白名单,并在验证时严格执行。