JWT 解码与安全验证完全指南
深入了解 JWT 的三段结构、解码方法、常见安全漏洞以及与 Session 的对比,帮助你安全地使用 JSON Web Token。
什么是 JWT?为什么你需要了解它
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。它以紧凑、URL 安全的方式编码声明,广泛应用于用户认证、信息交换和 API 授权。每当你登录一个现代 Web 应用,后台很可能就在使用 JWT 来管理你的会话。
理解 JWT 的结构和潜在风险,是每个开发者的基本功。我们的 JWT 解码器 让你快速查看令牌内容,而无需手动解码 Base64。
JWT 的三段结构
一个 JWT 由三部分组成,用点号(.)分隔:Header.Payload.Signature。每部分都是 Base64URL 编码的字符串。
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.D4fS12abc3
^--- Header ------^ ^--- Payload -----^ ^-- Signature --^
Header(头部)
Header 声明令牌类型和签名算法。典型的 Header 如下:
{
"alg": "HS256",
"typ": "JWT"
}
alg 指定签名算法,typ 固定为 "JWT"。常见算法包括 HS256(HMAC-SHA256)和 RS256(RSA-SHA256)。
Payload(载荷)
Payload 包含实际的声明(Claims)。声明分为三类:
- 注册声明:标准字段如
iss(签发者)、exp(过期时间)、sub(主题)、aud(受众)。 - 公共声明:自定义但需避免冲突的字段。
- 私有声明:双方约定的自定义字段,如用户角色、权限等。
{
"sub": "1234567890",
"name": "张三",
"role": "admin",
"iat": 1712345678,
"exp": 1712349278
}
⚠️ 重要提醒:Payload 仅是 Base64 编码,并非加密。任何人都可以解码并读取内容。
Signature(签名)
签名用于验证令牌在传输过程中未被篡改。计算方式:
// HMAC-SHA256 签名计算伪代码
signature = HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
);
对于 RS256 等非对称算法,签名使用私钥生成,公钥验证。这使得第三方可以在不共享密钥的情况下验证令牌。
如何解码 JWT
解码 JWT 只需将每段进行 Base64URL 解码。你可以在浏览器控制台中快速完成:
// 手动解码 JWT 的 Payload
function decodeJWT(token) {
const payload = token.split('.')[1];
const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));
return JSON.parse(decoded);
}
const token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.xxx';
console.log(decodeJWT(token));
// { sub: "12345" }
但这只是解码——解码不等于验证。验证签名需要密钥或公钥。使用我们的 JWT 解码器,粘贴令牌即可立即查看 Header 和 Payload 内容。
常见的安全错误
alg: none 攻击
某些库接受 "alg": "none",即不签名的令牌。攻击者可以修改 Payload 并移除签名,服务器若未正确校验算法则会接受伪造令牌。
{
"alg": "none"
}
防御:在服务器端硬编码允许的算法列表,不要依赖令牌中的 alg 字段。
使用弱密钥
HMAC 签名的安全性完全取决于密钥强度。如果使用 "secret"、"password" 等常见弱密钥,攻击者可以通过暴力破解伪造签名。
# ❌ 弱密钥
JWT_SECRET=secret
JWT_SECRET=123456
# ✅ 强密钥(至少 256 位随机字符串)
JWT_SECRET=Kj8#mP2$xN9@qR4!wL6^dF0&hT3*sY7
不验证过期时间
如果不检查 exp 声明,被盗的令牌将永久有效。务必在验证逻辑中包含过期检查。
在 Payload 中存储敏感信息
JWT Payload 只是 Base64 编码——任何人都可以读取。永远不要在 Payload 中存储密码、信用卡号等敏感数据。
JWT vs Session 对比
| 特性 | JWT | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务端 |
| 扩展性 | 无状态,天然适合分布式 | 需要共享会话存储 |
| 注销 | 困难(需要黑名单机制) | 简单(删除服务端记录) |
| 大小 | 较大(携带完整信息) | 较小(仅会话 ID) |
| 适用场景 | API、微服务、SSO | 传统 Web 应用 |
没有绝对更好的方案。JWT 适合无状态 API 和跨服务认证,Session 适合需要即时失效控制的传统应用。许多系统同时使用两者。
JWT 最佳实践
- 设置合理过期时间:Access Token 15-30 分钟,Refresh Token 7-30 天。
- 使用 HTTPS:JWT 在传输中应始终加密,防止中间人攻击。
- 验证所有声明:检查
iss、aud、exp,不要只验证签名。 - 选择合适的算法:对称(HS256)用于单服务,非对称(RS256)用于多服务。
- 实施 Token 轮换:每次刷新时签发新的 Refresh Token,旧的立即失效。
- 考虑黑名单:对于高安全场景,维护已撤销 Token 的黑名单。
常见问题
JWT 解码后能看到密码吗?
JWT Payload 是 Base64 编码的,任何人都可以解码查看内容。这就是为什么永远不要在 Payload 中存储密码或敏感信息。Payload 中通常只包含用户 ID、角色、过期时间等非敏感声明。
JWT 会不会被伪造?
只要密钥足够强且算法配置正确,JWT 签名无法被伪造。主要风险来自弱密钥、alg: none 漏洞、以及未正确验证签名的库。使用我们的 JWT 解码器 检查令牌结构,确保没有异常。
JWT 和 OAuth 2.0 是什么关系?
OAuth 2.0 是一个授权框架,JWT 是一种令牌格式。OAuth 2.0 可以使用 JWT 作为 Access Token 的格式,也可以使用其他格式(如不透明令牌)。两者常配合使用,但本质上是不同的东西。
JWT 太大怎么办?
减少 Payload 中的声明数量,只包含必要的信息。对于移动端或带宽敏感场景,考虑使用不透明令牌+服务端查询的方案,或压缩 Payload 内容。
总结
JWT 是现代 Web 认证的核心技术。掌握其结构(Header.Payload.Signature)、理解安全陷阱、遵循最佳实践,是构建安全应用的基础。使用我们的 JWT 解码器 快速查看和调试你的令牌——完全在浏览器中运行,你的数据不会离开设备。
试试这个工具?
打开工具 →