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 算法选择决策流程
下图展示了在系统设计阶段如何根据场景选择合适的签名算法:
3.6 头部常见安全陷阱
- 算法混淆攻击:攻击者将
alg从RS256改为HS256,并利用泄露的公钥作为 HMAC 密钥进行签名。防御措施:验证时强制绑定算法与密钥类型。 - 空算法攻击:将
alg改为none绕过签名验证。防御措施:拒绝none算法,白名单允许的算法列表。 - 算法降级:将强算法降级为弱算法。防御措施:服务端固定期望的算法,不信任客户端声明的算法。
核心要点:头部中的
alg 字段是 JWT 安全的第一道防线。永远不要信任客户端提供的算法声明,服务端应预先配置允许的算法白名单,并在验证时严格执行。