2. JWT 工作原理:客户端与服务端交互流程、Token 的签发与验证过程、无状态认证的优势
2.1 核心交互流程:从登录到鉴权
JWT 分布式鉴权的核心在于客户端持有凭证,服务端不保存会话状态。一次完整的交互流程分为两个阶段:签发阶段和验证阶段。
核心原则:服务端只负责“验票”,不负责“记人”。每次请求都携带完整的身份信息,由服务端独立验证。
阶段一:Token 签发(登录)
- 客户端发起登录请求:用户通过浏览器或移动端提交用户名、密码到服务端认证接口(如
/api/login)。 - 服务端验证身份:服务端查询数据库,校验用户名密码是否正确。
- 服务端签发 JWT:验证通过后,服务端将用户标识(如
userId)、角色、过期时间等数据放入 JWT 载荷,使用密钥(Secret)或私钥(Private Key)进行签名,生成一个完整的 JWT 字符串。 - 返回 Token:服务端将 JWT 返回给客户端(通常在 HTTP Response Body 或 Header 中)。
- 客户端存储 Token:客户端将 JWT 存储在本地(如浏览器的
localStorage、sessionStorage或移动端的本地存储)。
阶段二:Token 验证(请求)
- 客户端发起业务请求:客户端在请求头(通常是
Authorization: Bearer <token>)中携带 JWT。 - 服务端拦截并解析:服务端通过过滤器或拦截器获取请求头中的 JWT。
- 服务端验证签名:服务端使用相同的密钥或公钥验证 JWT 的签名是否有效,同时检查
exp(过期时间)等声明。 - 提取用户信息:验证通过后,服务端从 JWT 载荷中解析出用户身份和权限信息。
- 执行权限判断:服务端根据解析出的信息判断用户是否有权访问该资源。
- 返回业务数据:权限验证通过,服务端处理请求并返回结果。
2.2 Token 的签发与验证过程详解
JWT 的签发与验证是非对称或对称加密算法的典型应用。下面以最常用的 HS256(对称)和 RS256(非对称)为例,拆解其内部机制。
2.2.1 签发过程(Signing)
服务端将用户信息打包成 JWT 的三个部分,并生成签名。
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 构建 Header | 指定算法(如 HS256)和 Token 类型(JWT)。 |
| 2 | 构建 Payload | 放入标准声明(iss、exp、sub)和自定义声明(如 userId、role)。 |
| 3 | 编码 Header 和 Payload | 使用 Base64URL 编码,生成两个字符串。 |
| 4 | 生成签名 | 将编码后的 Header 和 Payload 用 . 连接,使用密钥进行 HMAC-SHA256 或 RSA-SHA256 计算,得到签名。 |
| 5 | 组合 JWT | 将 Header.Payload.Signature 用 . 连接,形成最终 Token。 |
关键点:签名是使用密钥对前两部分内容的哈希值进行加密的结果。任何对 Header 或 Payload 的篡改,都会导致签名验证失败。
2.2.2 验证过程(Verification)
服务端收到 JWT 后,执行逆向操作以确认 Token 的真实性和完整性。
- 拆分 Token:按
.将 JWT 拆分为 Header、Payload、Signature 三部分。 - 解码 Header:Base64URL 解码 Header,获取算法信息。
- 重新计算签名:使用相同的算法和密钥,对接收到的 Header 和 Payload 重新计算签名。
- 比对签名:将计算出的签名与 Token 中的签名进行比对。如果一致,则通过;否则拒绝。
- 校验声明:检查
exp(是否过期)、nbf(是否生效)、iss(是否可信)等。 - 提取数据:验证通过后,解码 Payload 获取用户信息。
2.3 无状态认证的优势
JWT 最核心的价值在于无状态(Stateless)。与传统的基于 Session 的有状态认证相比,它在分布式架构下具有显著优势。
| 对比维度 | 传统 Session 认证(有状态) | JWT 认证(无状态) |
|---|---|---|
| 存储位置 | Session 数据存储在服务端内存或 Redis 中。 | Token 数据存储在客户端,服务端不保存。 |
| 扩展性 | 需要 Session 共享(如 Redis 集中存储),否则多节点无法同步。 | 天然支持水平扩展,任何节点均可独立验证 Token。 |
| 性能 | 每次请求需查询 Session 存储,存在 I/O 开销。 | 仅需本地计算签名,无 I/O 开销,性能更高。 |
| 跨域/跨系统 | Session 难以跨域共享,需额外配置。 | Token 可轻松在多个微服务、移动端、第三方应用间传递。 |
| 安全性 | Session ID 泄露后,攻击者需获取服务端 Session 数据。 | Token 泄露后,攻击者直接获得用户身份,需配合 HTTPS 和短有效期。 |
| 服务端压力 | 大量用户在线时,Session 存储占用大量服务端资源。 | 服务端无需存储,资源消耗极低。 |
注意:无状态也意味着无法主动吊销 Token。如果用户密码泄露或需要强制下线,必须等待 Token 过期或依赖黑名单机制(黑名单会引入状态,需权衡使用)。
2.3.1 分布式场景下的核心优势
- 零共享:微服务 A 和微服务 B 不需要共享 Session 存储,各自使用相同的密钥即可验证 Token。
- 低延迟:验证过程是纯 CPU 计算,不依赖网络 I/O(如查询 Redis),适合高并发场景。
- 解耦:认证服务只负责签发 Token,业务服务只负责验证 Token,职责清晰。
2.3.2 适用场景与避坑
| 场景 | 推荐度 | 说明 |
|---|---|---|
| 单点登录(SSO) | ⭐⭐⭐⭐⭐ | JWT 天然适合跨系统身份传递。 |
| 移动端 API | ⭐⭐⭐⭐⭐ | 无 Cookie 依赖,适配原生存储。 |
| 微服务网关 | ⭐⭐⭐⭐⭐ | 网关统一验证 Token,下游服务无需重复鉴权。 |
| 需要强制吊销的场景 | ⭐⭐⭐ | 需配合黑名单或短有效期,增加复杂度。 |
最佳实践:在分布式系统中,建议使用 RS256(非对称)。认证服务持有私钥签发 Token,所有业务服务只持有公钥验证 Token。私钥不泄露,公钥可安全分发,安全性更高。