一、什么是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" // 令牌类型

}

解码结果示例:

Payload 编码值:W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE3NTQ4MzQ0MzIsImV4cCI6MTc1NDg0MTYzMiwibmJmIjoxNzU0ODM0NDMyLCJzdWIiOiJ1c2VyIiwianRpIjoiZGVlZmM2ZWRlNzY3YWRhMWZkMGY1ZmYyY2Y3OGMxZDcifV0

解码后(JSON 格式):

[

{

"iss": "admin", // 签发者

"iat": 1754834432, // 签发时间(Unix 时间戳)

"exp": 1754841632, // 过期时间(Unix 时间戳)

"nbf": 1754834432, // 生效时间(Unix 时间戳)

"sub": "user", // 主题(通常为用户标识)

"jti": "deeff6ede767ada1fd0f5ff2cf78c1d7" // 唯一令牌ID

}

]

解码结果示例:

可见,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(载荷)

包含两类声明:

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

iss(Issuer):签发者;

exp(Expiration Time):过期时间(Unix 时间戳);

iat(Issued At):签发时间(Unix 时间戳);

nbf(Not Before):生效时间(时间戳之前令牌无效);

sub(Subject):令牌主题(通常为用户 ID);

jti(JWT ID):唯一令牌 ID(用于防重放)。

自定义声明:业务相关数据(如用户邮箱、权限等级),不可存储密码、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 安全的核心,生成逻辑如下:

对 Header 和 Payload 分别进行 Base64URL 编码;

用 编码后的 Header + "." + 编码后的 Payload 拼接成字符串;

通过 Header 声明的算法(如 HS256),用密钥对拼接字符串进行加密哈希,得到 Signature。

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

Signature = HMAC-SHA256(

base64urlEncode(Header) + "." + base64urlEncode(Payload),

密钥(对称密钥,需保密)

)

示例 Signature:Xf55gOhhqwqJP4XR0pFUS_gZ-4vORVxUkp3JR3jVaYU

接收方通过相同逻辑计算签名并比对,一致则说明数据未被篡改。

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

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

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

2.1.1 攻击原理

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

将 非对称算法(如 RS256) 改为 对称算法(如 HS256):

服务器原本用 RS256(私钥签名、公钥验证),攻击者修改 alg: "HS256",并用服务器公开的公钥作为 HS256 的对称密钥,重新签名伪造令牌;

将 alg 改为 None(无算法):

部分实现会跳过签名验证,攻击者删除 Signature 部分(仅保留 Header.Payload.),直接篡改 Payload(如将 sub: "user" 改为 sub: "admin")。

2.1.2 攻击案例演示

以 alg: "None" 攻击为例:

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

eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOjAsImlhdCI6MTc1NDkzMjY0MywiZXhwIjoxNzU0OTM5ODQzLCJuYmYiOjE3NTQ5MzI2NDMsInN1YiI6ImFkbWluIiwianRpIjoiOTYzNTAyNjg0ZjZhZDNlZWQ1OTE0NDc0NmJjNTczNzIifQ.u7hvrDal1lzUxHLLEJkz5WdzajYv8xxGPcer3aI_6p0

解码结果:

篡改 Payload:

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

eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzMjY1MywiZXhwIjoxNzU0OTM5ODUzLCJuYmYiOjE3NTQ5MzI2NTMsInN1YiI6ImFkbWluIiwianRpIjoiOTMxMDk4M2QwM2Y2MTNiMmY3ZmUxZGJjYjg0MTBkZTQifQ

篡改过程:

删除 Signature:

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

eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzMjY1MywiZXhwIjoxNzU0OTM5ODUzLCJuYmYiOjE3NTQ5MzI2NTMsInN1YiI6ImFkbWluIiwianRpIjoiOTMxMDk4M2QwM2Y2MTNiMmY3ZmUxZGJjYjg0MTBkZTQifQ.

绕过验证:

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

2.1.3 防御措施

固定允许的算法列表:

服务器仅支持安全算法(如 RS256、ES256),拒绝 HS256(对称算法需严格保密密钥)、None 等危险算法;

强制校验 alg 字段:

验证时不依赖 JWT 自身声明的 alg,而是用配置的固定算法重新计算签名,不一致则直接拒绝;

禁用 None 算法:

所有 JWT 实现必须要求签名,明确禁用 alg: "None";

校验令牌格式:

确保 JWT 包含 Header.Payload.Signature 三部分,拒绝缺失 Signature 的令牌(如末尾仅含 . 的格式)。

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

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

2.2.1 常见弱密钥类型

简单字符串/常见密码:如 123456、password、secret、jwt123;

过短密钥:HS256 要求密钥至少 16 字节(128 位),若密钥长度 < 16 字节(如 abcdef、12345678),爆破成本极低;

可预测密钥:基于固定格式(如 company2023、jwt_202509)或业务信息(如域名、项目名)生成的密钥;

硬编码密钥:密钥直接写在前端 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 可执行文件:

步骤2:执行爆破

# 语法:./jwtcrack [待爆破的JWT字符串]

./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTc1NDkzNTY1NCwiZXhwIjoxNzU0OTQyODU0LCJuYmYiOjE3NTQ5MzU2NTQsInN1YiI6InVzZXIiLCJqdGkiOiI0M2Q4NDFmNDVmYTc4MTlkZDNjZTMzZTE2ZDRkOGNhYiJ9.0UcSGe4ohWq_8AML5Kc1ymvbjqHMAGb7d2fDfVuqETg

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

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

对称算法(HS256/HS512):

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

# 生成 32 字节(256 位)随机密钥(HS256 适用)

openssl rand -hex 32

# 输出示例:a3f2d4e5b6c7a8d9f0e1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3

非对称算法(RS256/ES256):

生成密钥对(私钥签名、公钥验证),私钥严格保密,公钥可公开:

# 生成 RSA 2048 位私钥(RS256 适用)

openssl genrsa -out private.key 2048

# 从私钥提取公钥(用于验证签名)

openssl rsa -in private.key -pubout -out public.key

密钥管理规范:

禁止硬编码密钥,使用环境变量、配置中心(如 Nacos、Apollo)或密钥管理服务(如 KMS)存储;

定期轮换密钥(如每 3 个月),并回收旧密钥;

严格控制密钥访问权限,仅授权服务端进程读取。

三、总结

3.1 JWT 核心要点

定义与作用:轻量级 JSON 令牌规范,通过数字签名保证信息安全,用于身份验证、信息交换等场景;

核心特点:

紧凑性:Base64 编码压缩 JSON 数据,便于传输;

自包含性:Header.Payload.Signature 三部分包含数据与校验机制;

结构细节:

Header:声明令牌类型和签名算法;

Payload:存储标准声明和自定义业务数据(明文,禁存敏感信息);

Signature:通过算法和密钥生成,验证数据完整性。

3.2 关键安全风险与防御

风险类型

攻击方式

核心防御措施

完整性未校验

篡改 alg 字段(如改为 HS256/None),绕过签名验证

1. 固定允许的算法列表;2. 强制校验 alg 与配置一致;3. 禁用 None 算法

弱密钥风险

暴力破解弱密钥(如 123456、短密钥),伪造令牌

1. 用 OpenSSL 生成安全密钥(HS256 至少 32 字节);2. 禁止硬编码,用配置中心存储密钥;3. 定期轮换密钥

3.3 最佳实践建议

不存储敏感信息:Payload 为 Base64 编码(可解码),禁止存储密码、Token、手机号等敏感数据;

设置合理过期时间:exp 字段建议设置较短有效期(如 1 小时),避免令牌泄露后被长期滥用;

使用非对称算法:优先选择 RS256/ES256 等非对称算法,私钥签名、公钥验证,降低密钥泄露风险;

结合 HTTPS 传输:JWT 通常在 HTTP 头中传输,需通过 HTTPS 防止中间人劫持和篡改。