JWT 解码教程:Token 三段结构详解
JWT(JSON Web Token)是现代 Web 应用的标准身份认证方式。登录后服务器返回一段长字符串,每次请求带上它。但这段字符串到底是什么?怎么解码查看?本文详解。
什么是 JWT?
JWT 是一种紧凑的、URL 安全的方式,用于在两方之间传递 JSON 信息。
标准格式
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJleHAiOjE3MjI1MDQwMDB9.K7gN1xVlmZW3pX4...
由三部分组成,用 . 分隔:
- Header(头部)
- Payload(载荷)
- Signature(签名)
通俗理解
JWT 像一张电子门票:
- Header:门票的印刷信息(什么纸、什么墨)
- Payload:门票内容(持票人是谁、有效期)
- Signature:防伪钢印(确保门票没被篡改)
三段结构详解
第 1 段:Header
Header 是 JSON 对象,描述 Token 的元信息:
{
"alg": "HS256",
"typ": "JWT"
}
alg:签名算法(HS256、RS256、ES256 等)typ:类型,固定为 JWT
Base64URL 编码后:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
第 2 段:Payload
Payload 是 JWT 的核心,存放声明(Claims):
{
"sub": "123",
"name": "John Doe",
"iat": 1722504000,
"exp": 1722590400
}
Base64URL 编码后:
eyJzdWIiOiIxMjMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3MjI1MDQwMDAsImV4cCI6MTcyMjU5MDQwMH0
注意:Payload 只是 Base64 编码,不是加密!任何人都能解码看到内容。不要放密码、密钥等敏感信息。
第 3 段:Signature
Signature 用于验证 Token 没被篡改:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
输出(用 HS256 算法):
K7gN1xVlmZW3pX4mYy6V6Q...
只有持有 secret 的人能生成有效签名,因此 Token 无法伪造。
标准 Claims(声明)
JWT 标准定义了 7 个保留 Claims:
| Claim | 含义 | 示例 |
| iss | 签发者 | "auth.example.com" |
| sub | 主体(用户 ID) | "123" |
| aud | 接收方 | "myapp.example.com" |
| exp | 过期时间(Unix 时间戳) | 1722590400 |
| nbf | 生效时间 | 1722504000 |
| iat | 签发时间 | 1722504000 |
| jti | 唯一 ID(用于撤销) | "abc-123" |
常见自定义 Claims
{
"sub": "123",
"name": "张三",
"role": "admin",
"email": "zhangsan@example.com",
"permissions": ["read", "write", "delete"]
}
52tool JWT 解码器
工具地址:JWT 解码器
功能
- 自动解析三段结构
- 显示 Header 和 Payload 的 JSON
- 显示签发时间、过期时间
- 显示剩余有效期
- 不验证签名(只解码)
- 浏览器端处理,Token 不外传
实战 1:解码 Token
输入:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoi5byg5LiJIiwiaWF0IjoxNzIyNTA0MDAwLCJleHAiOjE3MjI1OTA0MDB9.K7gN1xVlmZW3pX4...
输出:
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "123",
"name": "张三",
"iat": 1722504000,
"exp": 1722590400
}
// 时间信息
签发时间:2024-08-01 12:00:00
过期时间:2024-08-02 12:00:00
剩余:23 小时 59 分
实战 2:检查过期
如果 Token 已过期:
exp: 2020-01-01 00:00:00
状态:已过期 4 年
前端应跳转登录页或刷新 Token。
实战场景
场景 1:调试 API 401 错误
调用 API 返回 401 Unauthorized:
- 复制请求头中的
Authorization: Bearer - 粘贴到 JWT 解码器
- 检查
exp字段是否过期 - 检查
sub是否正确
场景 2:检查权限
{
"role": "user"
}
期望 admin 才能访问的接口返回 403 → 检查 JWT 中的 role 字段。
场景 3:调试跨域问题
CORS 报错时检查:
- Token 是否在
Authorization头 - 服务器是否配置允许该头部
- Token 是否包含必要 Claims
参考 CORS 检查工具。
场景 4:检查 Token 撤销
如果用了 jti 字段,服务器维护黑名单。解码查看 jti 是否在黑名单中。
JWT 签名算法
HS256(HMAC + SHA-256)
- 对称加密,客户端和服务器共享 secret
- 性能高,简单
- 适合单体应用
RS256(RSA + SHA-256)
- 非对称加密,私钥签名,公钥验证
- 公钥可公开,便于分布式验证
- 适合微服务
ES256(ECDSA + SHA-256)
- 椭圆曲线签名
- 比 RS256 更短更快
- 适合移动端、IoT
none
- 不签名,仅 Header + Payload + "."
- 极度不安全
- 有些漏洞是误配置成 none 算法被绕过
永远不要用 none 算法!
JWT 的优缺点
优点
- 无状态:服务器不需要存 Session
- 跨域:天然适合分布式
- 标准:RFC 7519,跨语言支持
- 自包含:Token 内有用户信息,省一次查库
缺点
- 不可撤销:签发后无法主动失效(除非黑名单)
- 体积大:比 Session ID 长
- 续期复杂:需要 Refresh Token
- Payload 不加密:不能放敏感数据
JWT 安全最佳实践
实践 1:HTTPS 传输
JWT 在 HTTP 中传输会被中间人窃取。永远用 HTTPS。
实践 2:设置短过期时间
{
"exp": 1722504000 + 3600
}
Access Token 过期 1 小时,配合 Refresh Token 续期。
实践 3:不要放敏感信息
Payload 不加密,任何人能解码。不要放:
- 密码
- 银行卡号
- 身份证号
- API 密钥
实践 4:用强 secret
HS256 的 secret 至少 32 字符随机字符串。用 52tool UUID 生成器 生成。
实践 5:验证算法
服务器端验证 alg 字段,拒绝 none 算法,防止算法降级攻击。
实践 6:Refresh Token
短期 Access Token + 长期 Refresh Token:
Access Token: 1 小时
Refresh Token: 30 天
Refresh Token 用于获取新 Access Token,避免用户频繁登录。
编程实现
JavaScript(前端)
// 解码(不验证签名)
function decodeJWT(token) {
const [header, payload, signature] = token.split('.');
return {
header: JSON.parse(atob(header)),
payload: JSON.parse(atob(payload)),
signature
};
}
// 检查过期
function isExpired(payload) {
return payload.exp < Date.now() / 1000;
}
JavaScript(后端,jsonwebtoken 库)
import jwt from 'jsonwebtoken';
// 签发
const token = jwt.sign({ sub: '123', name: '张三' }, 'secret', { expiresIn: '1h' });
// 验证 + 解码
const decoded = jwt.verify(token, 'secret');
Python
import jwt
# 签发
token = jwt.encode({'sub': '123', 'exp': datetime.utcnow() + timedelta(hours=1)}, 'secret', algorithm='HS256')
# 验证
decoded = jwt.decode(token, 'secret', algorithms=['HS256'])
Java(jjwt 库)
import io.jsonwebtoken.Jwts;
// 签发
String token = Jwts.builder()
.setSubject("123")
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(SignatureAlgorithm.HS256, "secret")
.compact();
// 验证
Claims claims = Jwts.parser()
.setSigningKey("secret")
.parseClaimsJws(token)
.getBody();
Go
import "github.com/golang-jwt/jwt/v5"
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": "123",
"exp": time.Now().Add(time.Hour).Unix(),
})
signed, _ := token.SignedString([]byte("secret"))
与其他工具配合
JWT + Base64
工具:Base64 编解码
JWT 三段都是 Base64URL 编码,可手动解码查看。
JWT + 时间戳
工具:时间戳转换
exp 字段是 Unix 时间戳,转可读时间用时间戳工具。
JWT + UUID
工具:UUID 生成器
jti 字段用 UUID 防止重放攻击。
JWT + CORS
工具:CORS 检查
跨域 API 调用需要正确配置 CORS 允许 Authorization 头。
常见问题解答
Q: JWT 加密吗?
A: JWT 标准只是签名(防篡改),不加密(防查看)。Payload 任何人都能解码看到。需要加密用 JWE(JSON Web Encryption)。
Q: JWT 怎么撤销?
A: 标准无法撤销。常用方案:1) 黑名单:服务器记录撤销的 jti,每次请求检查;2) 短过期:让 Token 自然失效;3) 版本号:用户改密码时增加 tokenVersion,旧 Token 失效。
Q: JWT 存哪里?
A: 推荐 HttpOnly Cookie,防 XSS 偷取。或浏览器内存(关闭即失效)。不要存 LocalStorage,易被 XSS 攻击。
Q: JWT 过期了怎么办?
A: 用 Refresh Token 换新 Access Token。Refresh Token 通常有效期更长,存在数据库可主动撤销。
Q: JWT 签名算法选哪个?
A: 单体应用选 HS256,简单高效。微服务选 RS256 或 ES256,公钥可公开便于各服务验证。
Q: 工具会泄露我的 JWT 吗?
A: 52tool JWT 解码器在浏览器端运行,Token 不上传服务器。但仍建议不要在生产环境粘贴真实 Token,开发测试 Token 即可。
总结
JWT 是现代 Web 认证标配:
- 解码查看 → 52tool JWT 解码器
- 签发实现 → 服务端库(jsonwebtoken、jjwt 等)
- 安全实践 → HTTPS、短过期、不存敏感信息
- 续期方案 → Refresh Token
记住:Payload 不加密,不要放密码;Signature 防篡改,但 Token 一旦签发无法撤销。