2、JWT工作原理:Token签发流程、客户端存储方式、服务端验证流程、无状态认证原理

JWT(JSON Web Token)是现代SaaS系统中应用最广泛的鉴权令牌标准。理解其工作原理,是构建安全、可扩展的鉴权链路的基础。本节将从Token的签发、存储、验证到无状态认证的核心思想,进行全链路拆解。

2.1 JWT的结构与组成

一个标准的JWT由三个部分通过“.”连接而成:Header(头部)、Payload(载荷)、Signature(签名)。其结构为:xxxxx.yyyyy.zzzzz。

组成部分 内容说明 是否可被客户端读取 是否可被客户端篡改
Header 声明令牌类型(typ: JWT)和签名算法(alg: HS256 / RS256) 是(Base64解码) 否(篡改后签名校验失败)
Payload 存放声明(Claims),如用户ID(sub)、过期时间(exp)、发行者(iss)等 是(Base64解码) 否(篡改后签名校验失败)
Signature 对Header和Payload的签名,用于验证令牌的完整性和真实性 是(仅作为签名值) 否(无密钥无法伪造)
安全提示:Payload虽然经过Base64编码,但并未加密。切勿在Payload中存放密码、信用卡号等敏感信息。如需加密,应使用JWE(JSON Web Encryption)标准。

2.2 Token签发流程

Token签发发生在用户成功登录之后。服务端验证用户凭证(用户名/密码、OAuth授权码等)通过后,生成JWT并返回给客户端。

核心步骤:
  1. 用户认证:客户端提交凭证(如用户名+密码)到服务端。
  2. 凭证校验:服务端验证凭证有效性(如查询数据库、LDAP等)。
  3. 构建Payload:将用户标识、角色、权限范围、过期时间等写入Payload。
  4. 生成签名:使用服务端私钥(RS256)或共享密钥(HS256)对Header和Payload进行签名。
  5. 返回Token:服务端将完整的JWT字符串返回给客户端。
JWT Token签发流程 客户端 服务端认证 签名生成 1. 提交凭证 2. 构建Payload 3. 返回JWT 关键说明 • 签名算法推荐使用非对称算法(RS256),私钥仅存于服务端,安全性更高。 • 过期时间(exp)应设置在15分钟到2小时之间,避免Token长期有效带来的风险。

2.3 客户端存储方式

客户端收到JWT后,需要将其安全地存储起来,以便在后续请求中携带。不同的存储方式直接影响安全性。

存储方式 实现方法 安全性 适用场景
localStorage / sessionStorage 通过JavaScript直接存储 低(易受XSS攻击) 仅用于开发环境或非敏感应用
HttpOnly Cookie 服务端设置Cookie,标记HttpOnly 高(无法被JavaScript读取,防XSS) 生产环境推荐,需配合CSRF防护
内存变量 存储在JS闭包或框架状态管理(如Vuex/Redux)中 中(刷新页面后丢失) 配合刷新Token机制使用
安全警告:禁止将JWT存储在localStorage中用于生产环境。一旦页面存在XSS漏洞,攻击者可以轻松窃取Token,实现持久化登录劫持。推荐使用HttpOnly Cookie + CSRF Token的组合方案。

2.4 服务端验证流程

当客户端发起受保护资源的请求时,服务端需要对携带的JWT进行严格验证。验证通过后,才允许访问资源。

验证步骤:
  1. 提取Token:从请求头(Authorization: Bearer <token>)或Cookie中提取JWT。
  2. 解析结构:将JWT按“.”分割,分别获取Header、Payload、Signature。
  3. 校验签名:使用服务端密钥对Header和Payload重新计算签名,与传入的Signature比对。
  4. 校验声明:检查exp(过期时间)、nbf(生效时间)、iss(发行者)等是否有效。
  5. 提取用户信息:从Payload中获取用户ID、角色等,注入到请求上下文中。
服务端JWT验证流程 1. 请求进入 2. 提取Token 3. 签名校验 4. 声明校验 5. 放行 / 拒绝 校验失败 → 返回401

2.5 无状态认证原理

无状态认证是JWT的核心优势之一。服务端不再需要维护Session会话信息,每个请求都携带了完整的用户认证信息。

对比维度 传统Session认证 JWT无状态认证
服务端存储 需要存储Session ID与用户信息的映射 无需存储,Token自包含用户信息
扩展性 水平扩展需共享Session(如Redis) 天然支持水平扩展,任何节点均可验证
性能 每次请求需查询Session存储 仅需计算签名,无需I/O查询
安全性 Session ID泄露风险较低(随机字符串) Token泄露后,在有效期内可被任意使用
主动失效 服务端可随时删除Session 无法主动失效,需等待过期或维护黑名单
设计建议:在SaaS多租户场景中,无状态认证的优势尤为明显。每个微服务实例都可以独立验证Token,无需共享会话存储。但需注意,Token的过期时间不宜过长,并应配合刷新Token(Refresh Token)机制,在保证无状态的同时,兼顾安全性和用户体验。

2.6 无状态认证的挑战与应对

无状态认证并非银弹,在实际SaaS系统中,需要解决以下关键挑战:

  • Token吊销问题:用户修改密码或管理员禁用账号后,已签发的Token仍然有效。解决方案:维护一个短TTL的Token黑名单(Redis),或使用短有效期Token + 刷新Token机制。
  • Token体积膨胀:Payload中携带过多声明会导致Token体积变大,增加网络开销。解决方案:仅存放核心声明(sub, exp, roles),其他信息通过API查询。
  • 密钥管理:使用对称密钥(HS256)时,所有服务必须共享同一密钥,存在泄露风险。解决方案:使用非对称算法(RS256/ES256),认证服务持有私钥,其他服务仅持有公钥。
实战避坑:不要在JWT的Payload中存放权限列表或租户ID列表。权限变更后,已签发的Token无法同步更新。正确的做法是在Payload中存放角色标识,服务端根据角色动态查询权限。