深入理解 JWT:结构、原理与安全隐患全解析

636 阅读5分钟

前言

在现代 Web 应用中,用户认证已不再局限于传统的 Session-Cookie 模型。特别是在前后端分离架构盛行、微服务广泛应用的背景下,JWT(JSON Web Token) 被越来越多的系统所采用,作为一种轻量、跨平台的身份验证解决方案。

然而,关于 JWT 的误用、误解乃至滥用也屡见不鲜。本文旨在以严谨的技术视角,系统性地剖析 JWT 的结构原理、使用场景、实现方式以及安全注意事项,为工程实践提供可参考的理论基础。

一、JWT 是什么?

JWT,全称 JSON Web Token,是一种用于在网络应用环境中传递声明的基于 JSON 的开放标准(RFC 7519)。其主要用途是在客户端和服务端之间安全地传递经过签名的认证信息

JWT 具有以下特点:

  • 自包含(Self-contained) :一个 token 中包含了所有需要验证用户身份的信息;
  • 无状态(Stateless) :不依赖服务端的会话存储;
  • 跨平台:基于 JSON,可在任何支持 HTTP 的系统中使用。

二、JWT 的结构组成

JWT 的结构非常简单,由三部分通过英文句点 . 分隔组成:

header.payload.signature

1. Header(头部)

头部用于描述该 JWT 的元信息,通常包括两部分:

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg:签名所使用的算法,如 HMAC SHA256 或 RSA;
  • typ:标明类型,这里是 JWT。

2. Payload(负载)

Payload 是 JWT 的核心部分,用于存放实际需要传递的信息(也称为 Claims)。可以包含三类声明:

  • Registered claims(预定义字段):

    • iss(issuer):签发人;
    • exp(expiration time):过期时间;
    • sub(subject):主题;
    • aud(audience):接收对象;
    • iat(issued at):签发时间;
    • nbf(not before):在此时间之前不可用;
  • Public claims:用户自定义的公开声明字段,建议使用 URI 命名防止冲突;

  • Private claims:系统私有的自定义字段,例如 userId, role, permissions

示例:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "exp": 1712345678
}

3. Signature(签名)

签名部分用于防止数据被篡改。构造方法如下:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

如果使用的是 RSA 或 ECDSA,签名将使用私钥生成,并使用公钥验证。


三、JWT 的典型使用流程

JWT 通常用于认证流程中,如下所示:

  1. 用户通过用户名和密码请求登录;

  2. 服务端验证成功后生成 JWT,并返回给客户端;

  3. 客户端将该 JWT 保存(通常在 LocalStorage 或 Cookie 中);

  4. 后续请求中,客户端在 Authorization Header 中添加 JWT:

    Authorization: Bearer <token>
    
  5. 服务端接收请求后,验证 JWT 的有效性(签名、过期时间等),并根据其中的 Payload 信息进行权限控制。


四、与传统 Session 的对比

特性SessionJWT
状态管理有状态,服务端保存 Session无状态,服务端不保存
跨服务共享需要依赖集中式 Session 存储天然支持,无需共享存储
安全性SessionID 泄露后即可被冒用Token 泄露后也可被冒用,必须加密传输
服务端扩展性需要共享 Session 存储更适合微服务架构
撤销机制支持(服务端控制)不支持(Token 在有效期内始终有效)

五、JWT 的常见误区与安全隐患

虽然 JWT 简洁高效,但在工程实践中,如果不了解其机制,极容易埋下安全隐患。以下是一些典型误区:

1. 滥用 JWT 储存敏感信息

JWT 是 明文编码(Base64Url),不是加密。任何拿到 Token 的人都可以解析出 Payload 内容,因此:

  • 不要将密码、银行卡号等敏感信息直接放入 Payload;
  • 如需保护敏感字段,应进行额外加密或避免使用 JWT。

2. 忽略 Token 的撤销机制

JWT 一旦签发就“自我生效”,服务端无法主动废弃,除非:

  • 设置较短的过期时间 exp
  • 配合 Redis 等机制实现黑名单(token revocation);
  • 使用刷新机制(Refresh Token + Access Token)设计双 token 策略。

3. 使用 none 算法漏洞

早期版本的 JWT 库允许 alg: none 绕过签名验证(即伪造 Token)。务必确认使用的 JWT 库不支持或默认禁用该算法。

4. 错误地将 JWT 存储在 localStorage

尽管 LocalStorage 易于使用,但不能防御 XSS 攻击。若攻击者注入恶意脚本,可轻松窃取 Token。

  • 更安全的做法是使用 HttpOnly Cookie 携带 JWT,并配合 CSRF 防护策略。

六、工程实践建议

  1. 选择合适的签名算法:生产环境优先考虑非对称加密算法(如 RS256);
  2. 合理设置 Token 生命周期:短生命周期 + 刷新机制 是兼顾安全与体验的常见做法;
  3. 避免在 Payload 中放入敏感信息
  4. 验证 expnbfissaud 等字段,防止 Token 滥用
  5. 限制 JWT 使用场景:适用于一次性认证或服务间调用,不适合用于实时权限变更控制。

七、JWT 在微服务和前后端分离中的应用

JWT 的无状态特性使其天然适用于以下场景:

  • 微服务之间的身份传递:服务 A 可验证来自服务 B 的 JWT,从而实现权限授权;
  • 移动端与 Web 应用共享认证逻辑:统一的 Token 验证接口,跨平台支持;
  • 单点登录(SSO)系统:通过中心认证服务签发 JWT,多系统共享认证结果。

但也需注意,越依赖 JWT,无状态设计带来的控制力越弱,例如强制下线、权限动态变化等需求实现成本较高。

八、结语

JWT 不是银弹。它确实为分布式系统和前后端解耦提供了灵活的认证机制,但如果盲目使用、不加限制,反而可能引发更大的安全风险。

在实际开发中,理解其原理、明确其适用场景、遵循安全最佳实践,才是正确使用 JWT 的根本。