JWT(JSON Web Token) 全解析:从原理结构到安全风险与防御实践

一、什么是JWT

pyjwt 使用教程https://blog.pcat.cc/%e5%ae%89%e8%a3%85%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95/Web/jwtcrack

1.1 核心定义

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

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

1.2 核心特点

1.2.1 紧凑性

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

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

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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [
    {
    "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:

1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cucmFucmFuLnh5eiIsImlhdCI6MTc1NDU4MTczNywiZXhwIjoxNzU1MTg2NTM3LCJkYXRhIjp7ImVtYWlsIjoiMjAyMjQ3MTY3N0BxcS5jb20iLCJuYW1lIjoiMjguNyIsImVuY29kZSI6ImJhc2U2NCIsInJlYmNudW0iOjMsInpzY29kZSI6Ii91cGxvYWRzL2ltYWdlcy96c2NvZGUvMjAyNS8wNy8yOS96c2NvZGVfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc3ODIwM182OTgyLmpwZyIsImRzYm9keSI6Ii91cGxvYWRzL2ltYWdlcy9kc2JvZHkvMjAyNS8wNy8yOS9kc2JvZHlfMjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzNfMTc1Mzc2OTU1NV81MDYxLnBuZyJ9fQ.Xf55gOhhqwqJP4XR0pFUS_gZ-4vORVxUkp3JR3jVaYU
  • Header:声明令牌类型(typ: "JWT")和签名算法(alg: "HS256");
  • Payload:包含标准声明(如 issexp)和自定义业务数据(如用户邮箱、图片路径);
  • 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):

1
2
3
4
{
"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):

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"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 算法为例,签名公式:

1
2
3
4
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"):

    1
    eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOjAsImlhdCI6MTc1NDkzMjY0MywiZXhwIjoxNzU0OTM5ODQzLCJuYmYiOjE3NTQ5MzI2NDMsInN1YiI6ImFkbWluIiwianRpIjoiOTYzNTAyNjg0ZjZhZDNlZWQ1OTE0NDc0NmJjNTczNzIifQ.u7hvrDal1lzUxHLLEJkz5WdzajYv8xxGPcer3aI_6p0

    解码结果:
    原始JWT解码

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

    1
    eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzMjY1MywiZXhwIjoxNzU0OTM5ODUzLCJuYmYiOjE3NTQ5MzI2NTMsInN1YiI6ImFkbWluIiwianRpIjoiOTMxMDk4M2QwM2Y2MTNiMmY3ZmUxZGJjYjg0MTBkZTQifQ

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

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

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

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

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

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzNTY1NCwiZXhwIjoxNzU0OTQyODU0LCJuYmYiOjE3NTQ5MzU2NTQsInN1YiI6InVzZXIiLCJqdGkiOiI0M2Q4NDFmNDVmYTc4MTlkZDNjZTMzZTE2ZDRkOGNhYiJ9.0UcSGe4ohWq_8AML5Kc1ymvbjqHMAGb7d2fDfVuqETg
步骤1:安装 jwtcrack
1
2
3
4
5
6
7
8
9
10
11
# 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:执行爆破
1
2
# 语法:./jwtcrack [待爆破的JWT字符串]
./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzNTY1NCwiZXhwIjoxNzU0OTQyODU0LCJuYmYiOjE3NTQ5MzU2NTQsInN1YiI6InVzZXIiLCJqdGkiOiI0M2Q4NDFmNDVmYTc4MTlkZDNjZTMzZTE2ZDRkOGNhYiJ9.0UcSGe4ohWq_8AML5Kc1ymvbjqHMAGb7d2fDfVuqETg

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

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

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

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

    1
    2
    3
    4
    5
    # 生成 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 防止中间人劫持和篡改。