JWT(JSON Web Token)的核心价值是 无状态传递可信信息 ,整个流程分为「服务器生成 Token」和「服务器验证 Token」两大环节,下面结合实战场景和代码思路,用大白话讲透每一步。
一、前置准备
在生成 Token 前,先确定 3 个核心要素:
- 算法 :选 HS256(对称加密,只有一个密钥,服务器自己用)
- 密钥 :服务器专属的 “防伪印章”,比如 mp (绝对不能泄露!)
- Payload 业务信息 :要传递的用户数据 + 过期时间,比如 userId:123 、 exp:过期时间戳
二、第一步:服务器生成 JWT Token
以用户登录成功为例,服务器生成 Token 分为 5 步:
1. 构建 Header(头部) #后端 #Java #每天一个知识点
Header 是 JWT 的 “规则说明”,固定包含两个字段:
- alg :签名算法,这里填 HS256
- typ :Token 类型,固定填 JWT
原始 JSON :
json
{ "alg": "HS256", "typ": "JWT"}转 Base64 编码 :将上面的 JSON 转成 Base64 字符串(可公开解码),得到:
plaintext
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9注意:Base64 是编码不是加密,任何人都能解码回原文。
2. 构建 Payload(载荷)
Payload 是 JWT 的 “业务数据载体”,存放需要传递的信息,建议只存非敏感数据 (因为可公开解码)。必须加 exp 字段(过期时间,Unix 秒级时间戳),避免 Token 永久有效。
原始 JSON (示例):
json
{ "userId": 123, "username": "张三", "role": "user", "exp": 1737646800 // 代表 2026-01-23 17:00:00 过期}转 Base64 编码 :得到 Base64 字符串:

plaintext
eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiLlvKDkuIkicm9sZSI6InVzZXIiLCJleHAiOjE3Mzc2NDY4MDB93. 拼接 Header 和 Payload
将 Header 的 Base64 串和 Payload 的 Base64 串用 . 连接,得到 待签名字符串 :
plaintext
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiLlvKDkuIkicm9sZSI6InVzZXIiLCJleHAiOjE3Mzc2NDY4MDB94. 生成 Signature(签名)—— 防篡改核心
这是 JWT 最关键的一步,目的是给 “待签名字符串” 盖一个 “防伪印章”。计算规则 :用服务器的密钥(比如 mp ) + 选定的 HS256 算法,对 “待签名字符串” 进行哈希计算,得到二进制签名 → 再转 Base64URL 编码(和 Base64 几乎一样,适配 URL 传输)。
伪代码逻辑 :
plaintext
签名原始值 = HMAC-SHA256(待签名字符串, 密钥"mp")签名Base64 = Base64URL编码(签名原始值)最终得到签名串(示例):
plaintext
xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx5. 组装完整 JWT Token
将「HeaderBase64」「PayloadBase64」「签名 Base64」三部分用 . 连接,就是最终的 JWT Token:
plaintext
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiLlvKDkuIkicm9sZSI6InVzZXIiLCJleHAiOjE3Mzc2NDY4MDB9.xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx服务器将这个 Token 返回给客户端,客户端后续请求时,需要携带这个 Token。
三、第二步:服务器验证 JWT Token(含防篡改 + 过期检查)
客户端携带 Token 访问接口时,服务器按以下 5 步验证,核心是 “重新算签名对比” 。
1. 拆 Token
服务器拿到 Token 后,按 . 分割为三部分:
- 第一部分: HeaderBase64
- 第二部分: PayloadBase64
- 第三部分: 客户端传过来的签名Base64
2. 解析 Header,确定验证算法
解码 HeaderBase64 得到 JSON 原文,读取 alg:HS256 → 确定用 HS256 算法验证签名。
3. 解析 Payload,检查是否过期
解码 PayloadBase64 得到 JSON 原文,提取 exp 字段的过期时间戳:
- 服务器获取自己的当前 Unix 秒级时间戳(比如 1737640800 ,代表 15:00)
- 时间对比 :✅ 当前时间戳 < exp 时间戳 → Token 未过期,继续下一步❌ 当前时间戳 ≥ exp 时间戳 → 直接拒绝请求(哪怕签名正确也没用)
4. 重新拼接 + 计算新签名
将分割得到的 HeaderBase64 和 PayloadBase64 再次拼接为待签名字符串:
plaintext
HeaderBase64.PayloadBase64用服务器的密钥 mp + HS256 算法,重新计算出一个 新的签名 Base64 。
5. 对比签名,判断 Token 是否合法
将服务器重新计算的 新签名 Base64 与客户端传过来的 原签名 Base64 对比:
- ✅ 签名一致 → Token 未被篡改,合法有效,服务器解析 Payload 中的用户信息(如 userId),处理业务请求
- ❌ 签名不一致 → Token 被篡改(比如黑客改了 userId),直接拒绝请求
四、关键场景:黑客篡改 Token 会发生什么?
假设黑客解码 Payload,将 userId:123 改为 userId:999 (想冒充管理员),再重新编码为 新 PayloadBase64 ,构造假 Token:
plaintext
HeaderBase64.新 PayloadBase64.原签名 Base64服务器验证时:
- 拼接 HeaderBase64.新PayloadBase64 得到新的待签名字符串
- 用密钥 mp 算出来的 新签名 ,和黑客传的 原签名 完全不一样
- 签名对比失败 → 验证不通过,请求被拒
五、核心结论
- 生成关键 :签名是 Header+Payload + 密钥的 “数字指纹”,密钥不泄露,签名就无法伪造。
- 验证关键 :先查过期时间,再对比签名,两步缺一不可。
- 防篡改关键 :只要 Header/Payload 有任何字符改动,重新计算的签名就会完全变化,黑客无法绕过。