深入了解Json Web Token之概念篇
字数 3412 2025-08-18 11:37:33

JSON Web Token (JWT) 全面解析

1. JWT 概述

JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在各方之间安全地传输信息作为 JSON 对象。JWT 的主要目的是在服务端和客户端之间以安全的方式来转移声明。

1.1 JWT 的主要应用场景

  1. 认证 (Authentication)
  2. 授权 (Authorization)
  3. 联合识别
  4. 客户端会话(无状态的会话)
  5. 客户端机密

1.2 JWT 相关术语

  • JWS (Signed JWT): 签名过的 JWT
  • JWE (Encrypted JWT): 部分 payload 经过加密的 JWT
  • JWK (JWT Key): JWT 的密钥(secret)
  • JWK set: JWT key set(非对称加密中需要密钥对)
  • JWA: 当前 JWT 所用到的密码学算法
  • nonsecure JWT: 当头部签名算法设为 none 时的 JWT(不安全)

2. JWT 的组成结构

一个标准的 JWT 由三部分组成,用点号 (.) 分隔:

xxxxx.yyyyy.zzzzz

2.1 Header (头部)

头部通常由两部分组成:

  1. 令牌类型(JWT)
  2. 使用的散列算法(如 HMAC SHA256 或 RSA)

可选部分

  • jti: JWT ID,在服务端应当唯一
  • cty: content type(当内容也带有 JWT 时设为 "jwt")

加密方式

base64UrlEncode(header)

2.2 Payload (载荷)

载荷包含声明(claims),分为三类:

  1. Registered Claims(注册声明):

    • iss (issuer): 发布者的 URL 地址
    • sub (subject): JWT 面向的用户
    • aud (audience): 接受者的 URL 地址
    • exp (expiration): JWT 销毁时间(Unix 时间戳)
    • nbf (not before): JWT 最早可用时间(Unix 时间戳)
    • iat (issued at): JWT 发布时间(Unix 时间戳)
    • jti (JWT ID): JWT 的唯一 ID 编号
  2. Public Claims: 由标准化组织根据需要定义

  3. Private Claims: 各方之间共享的自定义声明

加密方式

base64UrlEncode(payload)

安全注意事项

  • 不应在载荷中加入敏感数据(如密码)
  • 如需传输敏感数据,应使用 JWE 加密 payload

2.3 Signature (签名)

签名用于验证消息在传输过程中未被篡改。创建签名需要:

  1. 编码后的 header
  2. 编码后的 payload
  3. 密钥(secret)
  4. 头部中指定的算法

签名算法

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

支持的签名算法类型

  1. 对称加密 HMAC(哈希消息验证码):
    • HS256/HS384/HS512
  2. 非对称加密:
    • RSASSA(RSA 签名算法):RS256/RS384/RS512
    • ECDSA(椭圆曲线数据签名算法):ES256/ES384/ES512

3. JWS (Signed JWT)

JWS 是在 nonsecure JWT 基础上添加签名的 JWT。

3.1 JWS 验证过程

验证签名时,使用公钥或密钥解密签名,并与 base64UrlEncode(header) + base64UrlEncode(payload) 比较,一致则验证通过。

3.2 JWS 额外头部声明(可选)

  • jku: 发送 JWK 的地址(建议 HTTPS)
  • jwk: JWK
  • kid: JWK 的 ID 编号
  • x5u: 指向 X509 公共证书的 URL
  • x5c: X509 证书链
  • x5t: X509 证书的 SHA-1 指纹
  • x5t#S256: X509 证书的 SHA-256 指纹
  • typ: 类型声明(JOSE 或 JOSE+ JSON)
  • crit: 必须由解析器处理的声明名称数组

3.3 JWS 序列化(多重签名)

当需要多重签名时,使用 JWS 序列化结构:

{
  "payload": "<base64UrlEncode(payload)>",
  "signatures": [
    {
      "protected": "<base64UrlEncode(header)>",
      "header": "<JWS 额外声明>",
      "signature": "<签名>"
    }
  ]
}

4. JWE (Encrypted JWT)

JWE 用于保护数据不被第三方看到,比 JWS 更安全。

4.1 JWE 与 JWS 的区别

特性 JWS JWE
目的 验证数据 保护数据不被查看
密钥使用 私钥加密,公钥验证 公钥加密,私钥解密
数据修改 公钥持有者只能验证 公钥持有者可添加新数据

4.2 JWE 的构成

JWE 由五部分组成:

<protected header>.<encrypted key>.<initialization vector>.<cipher text>.<authentication tag>
  1. protected header: 类似 JWS 头部
  2. encrypted key: 加密密文的对称密钥
  3. initialization vector: 初始 IV 值
  4. cipher text: 密文数据
  5. authentication tag: 防止密文被篡改的附加数据

4.3 JWE 密钥加密算法

JWE 需要两种加密算法:

  1. 加密密钥的算法
  2. 加密内容的算法

密钥管理模式

  1. Key Encryption
  2. Key Wrapping
  3. Direct Key Agreement
  4. Key Agreement with Key Wrapping
  5. Direct Encryption

4.4 JWE Header 声明

  • type: 一般为 "jwt"
  • alg: 加密密钥的算法
  • enc: 加密内容的算法
  • zip: 压缩算法(如 "DEF" 表示 deflate)
  • 其他与 JWS 相同的声明(jku/jkw/kid/x5u/x5c/x5t/x5t#S256/typ/cty/crit)

4.5 JWE 加密过程

  1. 根据头部 alg 生成随机数
  2. 根据密钥管理模式确定加密密钥
  3. 确定 JWE 加密密钥(CEK)
  4. 计算初始 IV(如需要)
  5. 压缩明文(如 zip 声明存在)
  6. 使用 CEK、IV 和附加认证数据加密内容
  7. 压缩内容,返回 token

4.6 JWE 序列化

{
  "protected": "<base64UrlEncode(header)>",
  "unprotected": "<JWS 额外声明>",
  "iv": "<base64(IV)>",
  "aad": "<额外认证数据>",
  "ciphertext": "<base64(加密数据)>",
  "recipients": [
    {
      "header": "<密钥算法声明>",
      "encrypted_key": "<JWE 加密密钥>"
    }
  ]
}

5. JWT 工作原理

5.1 认证流程

  1. 用户使用凭据登录成功后,服务端返回 JWT
  2. 用户访问受保护资源时,在 Authorization 头中携带 JWT:
    Authorization: Bearer <token>
    
  3. 服务器验证 token 并返回对应内容

5.2 JWT 存储方式

  • HTTP-only Cookie(防 XSS)
  • localStorage
  • sessionStorage
  • Vuex(如使用 Vue)

5.3 跨域问题

使用 Authorization: Bearer 发送令牌不会引起跨域资源共享 (CORS) 问题,因为它不使用 cookie。

6. 算法选择建议

6.1 HMAC vs RSA/ECDSA

特性 HMAC RSA/ECDSA
类型 对称加密 非对称加密
适用场景 单点登录,一对一 一对多(如微服务架构)
速度 相对较慢
密钥管理 单一密钥 公钥/私钥对

建议

  • 单一应用、单一开发团队:使用 HMAC
  • 微服务架构、多团队开发:使用 RSA/ECDSA

6.2 算法选择考虑因素

  1. 安全性需求:高安全性场景优先选择 RSA/ECDSA
  2. 性能需求:高吞吐量场景可考虑 HMAC
  3. 密钥管理复杂度:HMAC 更简单,RSA/ECDSA 需要管理密钥对
  4. 系统架构:分布式系统更适合 RSA/ECDSA

7. 安全最佳实践

  1. 不要存储敏感信息在未加密的 payload 中
  2. 使用 HTTPS 传输 JWT
  3. 设置合理的过期时间exp 声明)
  4. 避免使用 none 算法
  5. 验证所有必需的声明(如 iss, aud, exp 等)
  6. 保护密钥:定期轮换,安全存储
  7. 考虑使用 JWE 传输敏感数据
  8. 防范重放攻击:可使用 jti 和短期有效的 token

8. 总结

JWT 提供了一种简洁、自包含的方式在各方之间安全传输信息。通过 JWS 实现数据验证,通过 JWE 实现数据加密,可以满足不同场景下的安全需求。在实际应用中,应根据具体需求选择合适的算法和实现方式,并遵循安全最佳实践以确保系统安全。

JSON Web Token (JWT) 全面解析 1. JWT 概述 JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在各方之间安全地传输信息作为 JSON 对象。JWT 的主要目的是在服务端和客户端之间以安全的方式来转移声明。 1.1 JWT 的主要应用场景 认证 (Authentication) 授权 (Authorization) 联合识别 客户端会话(无状态的会话) 客户端机密 1.2 JWT 相关术语 JWS (Signed JWT) : 签名过的 JWT JWE (Encrypted JWT) : 部分 payload 经过加密的 JWT JWK (JWT Key) : JWT 的密钥(secret) JWK set : JWT key set(非对称加密中需要密钥对) JWA : 当前 JWT 所用到的密码学算法 nonsecure JWT : 当头部签名算法设为 none 时的 JWT(不安全) 2. JWT 的组成结构 一个标准的 JWT 由三部分组成,用点号 (.) 分隔: 2.1 Header (头部) 头部通常由两部分组成: 令牌类型(JWT) 使用的散列算法(如 HMAC SHA256 或 RSA) 可选部分 : jti : JWT ID,在服务端应当唯一 cty : content type(当内容也带有 JWT 时设为 "jwt") 加密方式 : 2.2 Payload (载荷) 载荷包含声明(claims),分为三类: Registered Claims (注册声明): iss (issuer): 发布者的 URL 地址 sub (subject): JWT 面向的用户 aud (audience): 接受者的 URL 地址 exp (expiration): JWT 销毁时间(Unix 时间戳) nbf (not before): JWT 最早可用时间(Unix 时间戳) iat (issued at): JWT 发布时间(Unix 时间戳) jti (JWT ID): JWT 的唯一 ID 编号 Public Claims : 由标准化组织根据需要定义 Private Claims : 各方之间共享的自定义声明 加密方式 : 安全注意事项 : 不应在载荷中加入敏感数据(如密码) 如需传输敏感数据,应使用 JWE 加密 payload 2.3 Signature (签名) 签名用于验证消息在传输过程中未被篡改。创建签名需要: 编码后的 header 编码后的 payload 密钥(secret) 头部中指定的算法 签名算法 : 支持的签名算法类型 : 对称加密 HMAC(哈希消息验证码): HS256/HS384/HS512 非对称加密: RSASSA(RSA 签名算法):RS256/RS384/RS512 ECDSA(椭圆曲线数据签名算法):ES256/ES384/ES512 3. JWS (Signed JWT) JWS 是在 nonsecure JWT 基础上添加签名的 JWT。 3.1 JWS 验证过程 验证签名时,使用公钥或密钥解密签名,并与 base64UrlEncode(header) + base64UrlEncode(payload) 比较,一致则验证通过。 3.2 JWS 额外头部声明(可选) jku : 发送 JWK 的地址(建议 HTTPS) jwk : JWK kid : JWK 的 ID 编号 x5u : 指向 X509 公共证书的 URL x5c : X509 证书链 x5t : X509 证书的 SHA-1 指纹 x5t#S256 : X509 证书的 SHA-256 指纹 typ : 类型声明(JOSE 或 JOSE+ JSON) crit : 必须由解析器处理的声明名称数组 3.3 JWS 序列化(多重签名) 当需要多重签名时,使用 JWS 序列化结构: 4. JWE (Encrypted JWT) JWE 用于保护数据不被第三方看到,比 JWS 更安全。 4.1 JWE 与 JWS 的区别 | 特性 | JWS | JWE | |------|-----|-----| | 目的 | 验证数据 | 保护数据不被查看 | | 密钥使用 | 私钥加密,公钥验证 | 公钥加密,私钥解密 | | 数据修改 | 公钥持有者只能验证 | 公钥持有者可添加新数据 | 4.2 JWE 的构成 JWE 由五部分组成: protected header : 类似 JWS 头部 encrypted key : 加密密文的对称密钥 initialization vector : 初始 IV 值 cipher text : 密文数据 authentication tag : 防止密文被篡改的附加数据 4.3 JWE 密钥加密算法 JWE 需要两种加密算法: 加密密钥的算法 加密内容的算法 密钥管理模式 : Key Encryption Key Wrapping Direct Key Agreement Key Agreement with Key Wrapping Direct Encryption 4.4 JWE Header 声明 type : 一般为 "jwt" alg : 加密密钥的算法 enc : 加密内容的算法 zip : 压缩算法(如 "DEF" 表示 deflate) 其他与 JWS 相同的声明(jku/jkw/kid/x5u/x5c/x5t/x5t#S256/typ/cty/crit) 4.5 JWE 加密过程 根据头部 alg 生成随机数 根据密钥管理模式确定加密密钥 确定 JWE 加密密钥(CEK) 计算初始 IV(如需要) 压缩明文(如 zip 声明存在) 使用 CEK、IV 和附加认证数据加密内容 压缩内容,返回 token 4.6 JWE 序列化 5. JWT 工作原理 5.1 认证流程 用户使用凭据登录成功后,服务端返回 JWT 用户访问受保护资源时,在 Authorization 头中携带 JWT: 服务器验证 token 并返回对应内容 5.2 JWT 存储方式 HTTP-only Cookie(防 XSS) localStorage sessionStorage Vuex(如使用 Vue) 5.3 跨域问题 使用 Authorization: Bearer 发送令牌不会引起跨域资源共享 (CORS) 问题,因为它不使用 cookie。 6. 算法选择建议 6.1 HMAC vs RSA/ECDSA | 特性 | HMAC | RSA/ECDSA | |------|------|-----------| | 类型 | 对称加密 | 非对称加密 | | 适用场景 | 单点登录,一对一 | 一对多(如微服务架构) | | 速度 | 快 | 相对较慢 | | 密钥管理 | 单一密钥 | 公钥/私钥对 | 建议 : 单一应用、单一开发团队:使用 HMAC 微服务架构、多团队开发:使用 RSA/ECDSA 6.2 算法选择考虑因素 安全性需求 :高安全性场景优先选择 RSA/ECDSA 性能需求 :高吞吐量场景可考虑 HMAC 密钥管理复杂度 :HMAC 更简单,RSA/ECDSA 需要管理密钥对 系统架构 :分布式系统更适合 RSA/ECDSA 7. 安全最佳实践 不要存储敏感信息 在未加密的 payload 中 使用 HTTPS 传输 JWT 设置合理的过期时间 ( exp 声明) 避免使用 none 算法 验证所有必需的声明 (如 iss , aud , exp 等) 保护密钥 :定期轮换,安全存储 考虑使用 JWE 传输敏感数据 防范重放攻击 :可使用 jti 和短期有效的 token 8. 总结 JWT 提供了一种简洁、自包含的方式在各方之间安全传输信息。通过 JWS 实现数据验证,通过 JWE 实现数据加密,可以满足不同场景下的安全需求。在实际应用中,应根据具体需求选择合适的算法和实现方式,并遵循安全最佳实践以确保系统安全。