• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
28.7的博客
等小白学会了游泳,我们天天海边,学会了滑板,我们夏天去冲浪冬天去滑雪,只要你愿意,我们去经历各种各样有趣的事情~ “鸡毛!我学会了发现冰激凌烧烤奶茶火锅,我们天天去吃!现在就去!” “●﹏●;”
博客园    首页    新随笔    联系   管理    订阅  订阅
JWT(JSON Web Token) 全解析:从原理结构到安全风险与防御实践
JWT(JSON Web Token) 全解析:从原理结构到安全风险与防御实践 本文详解 JWT:作为轻量级 JSON 令牌规范,其由 Header(声明类型与算法)、Payload(存储标准 / 自定义数据,Base64 编码明文)、Signature(加密哈希验完整性)组成,兼具紧凑(易传输)与自包含(内置校验)特点,多用于身份验证与信息交换。重点分析两类高风险:算法篡改(如改 alg 为 None 绕过验证)、弱密钥(易被暴力破解),对应防御含固定安全算法、禁用 None、生成 32 字节以上随机密钥等。最后建议不存敏感信息、设短有效期、用非对称算法并结合 HTTPS

一、什么是JWT

pyjwt 使用教程

1.1 核心定义

JWT(JSON Web Token)是一种紧凑、自包含的轻量级规范,用于在网络各方之间安全传递 JSON 格式的声明信息。它通过数字签名保证信息的完整性和真实性,常见应用场景包括:

  • 身份验证(如用户登录后携带令牌访问接口)
  • 信息交换(如服务间传递可信业务数据)
  • 单点登录(SSO)、用户权限标记等

1.2 核心特点

1.2.1 紧凑性

JWT 通过 Base64 编码将复杂 JSON 数据压缩为简短字符串,便于在 URL、HTTP 头或 Cookie 中传输。
例如以下简化版 JWT(仅含 Header.Payload,无 Signature),解码后可直接获取原始 JSON 数据:

eyJhbGciOiJoczI1NiIsInR5cCI6Imp3dCJ9.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3NTQ4MzQ0MzIsImV4cCI6MTc1NDg0MTYzMiwibmJmIjoxNzU0ODM0NDMyLCJzdWIiOiJ1c2VyIiwianRpIjoiZGVlZmM2ZWRlNzY3YWRhMWZkMGY1ZmYyY2Y3OGMxZDcifV0
  • Header 编码值:eyJhbGciOiJOb25lIiwidHlwIjoiand0In0
    解码后(JSON 格式):

    {
      "alg": "None",  // 签名算法(此处为无算法)
      "typ": "jwt"    // 令牌类型
    }
    

    解码结果示例:
    Header解码结果

  • Payload 编码值:W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3NTQ4MzQ0MzIsImV4cCI6MTc1NDg0MTYzMiwibmJmIjoxNzU0ODM0NDMyLCJzdWIiOiJ1c2VyIiwianRpIjoiZGVlZmM2ZWRlNzY3YWRhMWZkMGY1ZmYyY2Y3OGMxZDcifV0
    解码后(JSON 格式):

    [
      {
        "iss": "admin",    // 签发者
        "iat": 1754834432, // 签发时间(Unix 时间戳)
        "exp": 1754841632, // 过期时间(Unix 时间戳)
        "nbf": 1754834432, // 生效时间(Unix 时间戳)
        "sub": "user",     // 主题(通常为用户标识)
        "jti": "deeff6ede767ada1fd0f5ff2cf78c1d7" // 唯一令牌ID
      }
    ]
    

    解码结果示例:
    Payload解码结果

可见,JWT 用简短字符串即可表达复杂 JSON 数据,传输效率极高。

1.2.2 自包含性

完整的 JWT 由 Header.Payload.Signature 三部分组成,不仅包含业务数据,还内置自校验机制。
例如以下完整 JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cucmFucmFuLnh5eiIsImlhdCI6MTc1NDU4MTczNywiZXhwIjoxNzU1MTg2NTM3LCJkYXRhIjp7ImVtYWlsIjoiMjAyMjQ3MTY3N0BxcS5jb20iLCJuYW1lIjoiMjguNyIsImVuY29kZSI6ImJhc2U2NCIsInJlYmNudW0iOjMsInpzY29kZSI6Ii91cGxvYWRzL2ltYWdlcy96c2NvZGUvMjAyNS8wNy8yOS96c2NvZGVfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc3ODIwM182OTgyLmpwZyIsImRzYm9keSI6Ii91cGxvYWRzL2ltYWdlcy9kc2JvZHkvMjAyNS8wNy8yOS9kc2JvZHlfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc2OTU1NV81MDYxLnBuZyJ9fQ.Xf55gOhhqwqJP4XR0pFUS_gZ-4vORVxUkp3JR3jVaYU
  • Header:声明令牌类型(typ: "JWT")和签名算法(alg: "HS256");
  • Payload:包含标准声明(如 iss、exp)和自定义业务数据(如用户邮箱、图片路径);
  • Signature:通过 Header 指定的 HS256 算法,对 编码后的 Header + "." + 编码后的 Payload 用密钥签名生成,用于验证数据未被篡改。

验证逻辑:接收方用相同密钥和算法重新计算 Header.Payload 的签名,与 JWT 中的 Signature 比对,一致则说明数据未被篡改。

1.3 JWT 完整解构

JWT 三部分的具体含义和格式如下表所示:

组成部分 编码方式 核心作用 示例(解码后)
Header(头部) Base64URL 声明令牌类型和签名算法 json { "typ": "JWT", "alg": "HS256" }
Payload(载荷) Base64URL 存储标准声明和自定义业务数据(明文,不可存敏感信息) json { "iss": "www.ranran.xyz", "iat": 1754581737, "exp": 1755186537, "data": { "email": "2022471677@qq.com" } }
Signature(签名) 加密哈希 验证数据完整性和真实性,防止篡改 Xf55gOhhqwqJP4XR0pFUS_gZ-4vORVxUkp3JR3jVaYU

1.3.1 Header(头部)

固定包含两个字段:

  • typ:令牌类型,固定为 JWT;
  • alg:签名算法,常见值包括 HS256(对称算法)、RS256(非对称算法)、ES256(椭圆曲线算法)等。

编码前示例(JSON):

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

编码后:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

1.3.2 Payload(载荷)

包含两类声明:

  1. 标准声明(可选,但推荐使用):

    • iss(Issuer):签发者;
    • exp(Expiration Time):过期时间(Unix 时间戳);
    • iat(Issued At):签发时间(Unix 时间戳);
    • nbf(Not Before):生效时间(时间戳之前令牌无效);
    • sub(Subject):令牌主题(通常为用户 ID);
    • jti(JWT ID):唯一令牌 ID(用于防重放)。
  2. 自定义声明:业务相关数据(如用户邮箱、权限等级),不可存储密码、token 等敏感信息(因 Base64 编码可直接解码)。

编码前示例(JSON):

{
  "iss": "www.ranran.xyz",
  "iat": 1754581737,
  "exp": 1755186537,
  "data": {
    "email": "2022471677@qq.com",
    "name": "28.7",
    "encode": "base64",
    "rebcount": 3,
    "zscode": "/uploads/images/zscode/2025/07/29/zscode_21232f297a57a5a743894a0e4a801fc3_1753778203_6982.jpg",
    "dsbody": "/uploads/images/dsbody/2025/07/29/dsbody_21232f297a57a5a743894a0e4a801fc3_1753769555_5061.png"
  }
}

编码后:eyJpc3MiOiJ3d3cucmFucmFuLnh5eiIsImlhdCI6MTc1NDU4MTczNywiZXhwIjoxNzU1MTg2NTM3LCJkYXRhIjp7ImVtYWlsIjoiMjAyMjQ3MTY3N0BxcS5jb20iLCJuYW1lIjoiMjguNyIsImVuY29kZSI6ImJhc2U2NCIsInJlYmNudW0iOjMsInpzY29kZSI6Ii91cGxvYWRzL2ltYWdlcy96c2NvZGUvMjAyNS8wNy8yOS96c2NvZGVfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc3ODIwM182OTgyLmpwZyIsImRzYm9keSI6Ii91cGxvYWRzL2ltYWdlcy9kc2JvZHkvMjAyNS8wNy8yOS9kc2JvZHlfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc2OTU1NV81MDYxLnBuZyJ9fQ

1.3.3 Signature(签名)

签名是 JWT 安全的核心,生成逻辑如下:

  1. 对 Header 和 Payload 分别进行 Base64URL 编码;
  2. 用 编码后的 Header + "." + 编码后的 Payload 拼接成字符串;
  3. 通过 Header 声明的算法(如 HS256),用密钥对拼接字符串进行加密哈希,得到 Signature。

以 HS256 算法为例,签名公式:

Signature = HMAC-SHA256(
  base64urlEncode(Header) + "." + base64urlEncode(Payload),
  密钥(对称密钥,需保密)
)

示例 Signature:Xf55gOhhqwqJP4XR0pFUS_gZ-4vORVxUkp3JR3jVaYU
接收方通过相同逻辑计算签名并比对,一致则说明数据未被篡改。

二、常见的JWT高风险管理措施

JWT 的安全依赖于 签名验证 和 密钥安全,若存在配置不当或实现缺陷,会导致严重安全风险。以下是两类典型高风险场景及防御方案。

2.1 未校验完整性(算法篡改攻击)

2.1.1 攻击原理

攻击者通过篡改 Header 中的 alg 字段,绕过签名验证,伪造恶意令牌。常见攻击方式:

  1. 将 非对称算法(如 RS256) 改为 对称算法(如 HS256):
    服务器原本用 RS256(私钥签名、公钥验证),攻击者修改 alg: "HS256",并用服务器公开的公钥作为 HS256 的对称密钥,重新签名伪造令牌;
  2. 将 alg 改为 None(无算法):
    部分实现会跳过签名验证,攻击者删除 Signature 部分(仅保留 Header.Payload.),直接篡改 Payload(如将 sub: "user" 改为 sub: "admin")。

2.1.2 攻击案例演示

以 alg: "None" 攻击为例:

  1. 原始 JWT(含签名,alg: "None"):

    eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOjAsImlhdCI6MTc1NDkzMjY0MywiZXhwIjoxNzU0OTM5ODQzLCJuYmYiOjE3NTQ5MzI2NDMsInN1YiI6ImFkbWluIiwianRpIjoiOTYzNTAyNjg0ZjZhZDNlZWQ1OTE0NDc0NmJjNTczNzIifQ.u7hvrDal1lzUxHLLEJkz5WdzajYv8xxGPcer3aI_6p0
    

    解码结果:
    原始JWT解码

  2. 篡改 Payload:
    将 iss: 0 改为 iss: "admin",sub: "admin" 保持不变,重新编码 Header 和 Payload:

    eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzMjY1MywiZXhwIjoxNzU0OTM5ODUzLCJuYmYiOjE3NTQ5MzI2NTMsInN1YiI6ImFkbWluIiwianRpIjoiOTMxMDk4M2QwM2Y2MTNiMmY3ZmUxZGJjYjg0MTBkZTQifQ
    

    篡改过程:
    篡改Payload
    重新编码

  3. 删除 Signature:
    保留 Header.Payload.(末尾加 . 符合格式),得到恶意令牌:

    eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzMjY1MywiZXhwIjoxNzU0OTM5ODUzLCJuYmYiOjE3NTQ5MzI2NTMsInN1YiI6ImFkbWluIiwianRpIjoiOTMxMDk4M2QwM2Y2MTNiMmY3ZmUxZGJjYjg0MTBkZTQifQ.
    
  4. 绕过验证:
    若服务器未校验 alg 字段且允许 None 算法,会直接信任恶意令牌,攻击者可冒充管理员登录:
    恶意令牌登录成功

2.1.3 防御措施

  1. 固定允许的算法列表:
    服务器仅支持安全算法(如 RS256、ES256),拒绝 HS256(对称算法需严格保密密钥)、None 等危险算法;
  2. 强制校验 alg 字段:
    验证时不依赖 JWT 自身声明的 alg,而是用配置的固定算法重新计算签名,不一致则直接拒绝;
  3. 禁用 None 算法:
    所有 JWT 实现必须要求签名,明确禁用 alg: "None";
  4. 校验令牌格式:
    确保 JWT 包含 Header.Payload.Signature 三部分,拒绝缺失 Signature 的令牌(如末尾仅含 . 的格式)。

2.2 弱密钥风险(暴力破解攻击)

对称算法(如 HS256)的安全性完全依赖于密钥强度,若密钥为弱密钥,攻击者可通过暴力破解工具(如 jwtcrack)爆破密钥,进而伪造任意令牌。

2.2.1 常见弱密钥类型

  1. 简单字符串/常见密码:如 123456、password、secret、jwt123;
  2. 过短密钥:HS256 要求密钥至少 16 字节(128 位),若密钥长度 < 16 字节(如 abcdef、12345678),爆破成本极低;
  3. 可预测密钥:基于固定格式(如 company2023、jwt_202509)或业务信息(如域名、项目名)生成的密钥;
  4. 硬编码密钥:密钥直接写在前端 JS、后端源码(如 const secret = "mykey";),易通过代码泄露获取。

2.2.2 爆破案例演示(使用 jwtcrack)

以如下 JWT 为例(密钥为弱密钥 123456):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzNTY1NCwiZXhwIjoxNzU0OTQyODU0LCJuYmYiOjE3NTQ5MzU2NTQsInN1YiI6InVzZXIiLCJqdGkiOiI0M2Q4NDFmNDVmYTc4MTlkZDNjZTMzZTE2ZDRkOGNhYiJ9.0UcSGe4ohWq_8AML5Kc1ymvbjqHMAGb7d2fDfVuqETg
步骤1:安装 jwtcrack
# 1. 克隆源码
git clone https://github.com/brendan-rius/c-jwt-cracker
cd c-jwt-cracker

# 2. 安装依赖(Python JWT库、OpenSSL开发包)
pip install pyjwt
apt-get install -y libssl-dev  # Ubuntu/Debian 系统
# yum install -y openssl-devel  # CentOS 系统

# 3. 编译(指定OpenSSL路径,适配不同系统)
make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl/lib

编译成功后生成 jwtcrack 可执行文件:
jwtcrack编译结果

步骤2:执行爆破
# 语法:./jwtcrack [待爆破的JWT字符串]
./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzNTY1NCwiZXhwIjoxNzU0OTQyODU0LCJuYmYiOjE3NTQ5MzU2NTQsInN1YiI6InVzZXIiLCJqdGkiOiI0M2Q4NDFmNDVmYTc4MTlkZDNjZTMzZTE2ZDRkOGNhYiJ9.0UcSGe4ohWq_8AML5Kc1ymvbjqHMAGb7d2fDfVuqETg

由于密钥为弱密钥 123456,工具会快速爆破成功,输出密钥。

2.2.3 防御措施(生成安全密钥)

  1. 对称算法(HS256/HS512):
    使用密码学安全的随机数生成器,生成足够长度的密钥(HS256 至少 32 字节/256 位):

    # 生成 32 字节(256 位)随机密钥(HS256 适用)
    openssl rand -hex 32
    # 输出示例:a3f2d4e5b6c7a8d9f0e1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3
    
  2. 非对称算法(RS256/ES256):
    生成密钥对(私钥签名、公钥验证),私钥严格保密,公钥可公开:

    # 生成 RSA 2048 位私钥(RS256 适用)
    openssl genrsa -out private.key 2048
    
    # 从私钥提取公钥(用于验证签名)
    openssl rsa -in private.key -pubout -out public.key
    
  3. 密钥管理规范:

    • 禁止硬编码密钥,使用环境变量、配置中心(如 Nacos、Apollo)或密钥管理服务(如 KMS)存储;
    • 定期轮换密钥(如每 3 个月),并回收旧密钥;
    • 严格控制密钥访问权限,仅授权服务端进程读取。

三、总结

3.1 JWT 核心要点

  1. 定义与作用:轻量级 JSON 令牌规范,通过数字签名保证信息安全,用于身份验证、信息交换等场景;
  2. 核心特点:
    • 紧凑性:Base64 编码压缩 JSON 数据,便于传输;
    • 自包含性:Header.Payload.Signature 三部分包含数据与校验机制;
  3. 结构细节:
    • Header:声明令牌类型和签名算法;
    • Payload:存储标准声明和自定义业务数据(明文,禁存敏感信息);
    • Signature:通过算法和密钥生成,验证数据完整性。

3.2 关键安全风险与防御

风险类型 攻击方式 核心防御措施
完整性未校验 篡改 alg 字段(如改为 HS256/None),绕过签名验证 1. 固定允许的算法列表;
2. 强制校验 alg 与配置一致;
3. 禁用 None 算法
弱密钥风险 暴力破解弱密钥(如 123456、短密钥),伪造令牌 1. 用 OpenSSL 生成安全密钥(HS256 至少 32 字节);
2. 禁止硬编码,用配置中心存储密钥;
3. 定期轮换密钥

3.3 最佳实践建议

  1. 不存储敏感信息:Payload 为 Base64 编码(可解码),禁止存储密码、Token、手机号等敏感数据;
  2. 设置合理过期时间:exp 字段建议设置较短有效期(如 1 小时),避免令牌泄露后被长期滥用;
  3. 使用非对称算法:优先选择 RS256/ES256 等非对称算法,私钥签名、公钥验证,降低密钥泄露风险;
  4. 结合 HTTPS 传输:JWT 通常在 HTTP 头中传输,需通过 HTTPS 防止中间人劫持和篡改。
posted on 2025-11-11 14:30  28的博客  阅读(37)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3

摘自:28.7的博客

蜀ICP备2025124055号-2