找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3517

积分

0

好友

480

主题
发表于 16 小时前 | 查看: 2| 回复: 0

所有技术八股文都告诉你JWT是去中心化、无状态的,但为什么在实际项目中,超过80%的团队最终还是选择了Token结合Redis的方案?难道大家真的是“嘴上说不要,身体很诚实”吗?今天我们就来彻底分析一下这两种方案,看看背后的技术选型逻辑究竟如何。

JWT方案的工作流程

首先,我们来梳理一下JWT(JSON Web Token)的典型实现步骤。当用户登录时,服务器端会生成一个JWT字符串,其中包含了用户信息、过期时间以及一个数字签名,然后将其返回给浏览器。接下来,浏览器会保存这个JWT(通常放在LocalStorage或Cookie中)。

当用户后续发起任何业务接口请求时,浏览器都会在HTTP请求头(例如 Authorization: Bearer <token>)中携带这个JWT。服务器端在接收到请求后,会首先校验JWT的合法性,这主要包括:检查令牌格式是否正确、是否已过期,以及验证签名是否有效。由于服务器本身(无论是本地内存、Redis还是数据库)不会存储任何关于JWT会话的数据,因此它被认为是“无状态”的。

如果校验成功,服务器会直接解析JWT负载(Payload)中的用户信息,并据此处理业务逻辑,最后将结果返回。如果校验失败(签名错误、格式非法)或者JWT已过期,服务器则会返回认证失败的信息,要求用户重新登录。

JWT交互流程图

Token + Redis方案的工作流程

接下来,我们看看另一种常见的方案:使用自生成的Token配合Redis存储。在用户登录时,服务器会生成一个唯一的Token(例如使用UUID算法),并将其返回给浏览器保存。

与此同时,服务器端会将这个Token作为键(Key),将用户的核心信息(如用户ID、角色等)序列化为字符串后作为值(Value),一并存入Redis中,并通常会设置一个过期时间。存储的数据格式可能如下所示:

{
  "userId": "10086",
  "username": "zhangsan",
  "role": "admin",
  "deviceId": "ios_123456789",
  "loginIp": "192.168.1.100",
  "createTime": 1740000000000,
  "expireTime": 1740072000000
}

之后,浏览器在发起业务请求时同样会在请求头中携带此Token。服务器收到请求后,会以这个Token为Key去Redis中查询。如果查询到对应的数据且未过期,则视为Token合法;否则即为非法或已过期。因为会话状态(Token与用户信息的映射关系)被显式地存储在服务器端的Redis中,所以这个方案是“有状态”的。

校验成功后,服务器直接从Redis读取用户信息来处理业务逻辑并返回结果。校验失败则提示用户重新登录。

Token+Redis交互流程图

表面优势与隐藏问题

乍一看,JWT方案似乎更具优势。它省去了在服务端存储Token的环节,简化了架构。而且,如果使用Token+Redis方案,一旦Redis服务宕机,整个系统的认证功能就可能瘫痪;如果存储在数据库,高频的Token校验查询又会给数据库带来巨大压力。JWT方案看起来完美避开了这些烦恼。

但事情真有这么简单吗?软件开发中有一个朴素的道理:有正向操作,就必然存在逆向操作。既然有用户登录,就一定会有用户退出登录。那么,问题来了。

对于Token+Redis方案,实现“退出登录”功能非常直观:只需要从Redis中删除对应的Key即可,用户的Token立即失效。然而,对于标榜“无状态”的JWT,该如何实现立即失效呢?

你可能会想到一个办法:引入一个“黑名单”机制。当用户退出登录时,将其JWT存入Redis的黑名单中。后续每次校验JWT时,除了常规的格式、过期和验签检查,还要额外去查询一下这个黑名单。如果JWT在黑名单中,则拒绝请求。

但这就引出了一个核心矛盾:JWT方案最初以“无状态”、“去中心化”作为主要卖点,可为了实现关键的“立即退出登录”功能,却又不得不依赖外部的存储(如Redis)来维持一个状态(黑名单)。这岂不是一种自我否定?

深入思考与选择

正是这个看似微小的“退出登录”需求,揭示了JWT在真实业务场景中的局限性。它无法在不解耦架构的前提下,单方面地使一个已颁发的令牌失效。除此之外,JWT一旦签发,在有效期内其包含的信息(如用户角色)也无法主动更新,这在权限变更频繁的场景下也是一个问题。

相比之下,Token+Redis方案虽然引入了状态存储,但在系统架构上却更加灵活和可控。它可以轻松实现:

  1. 立即登出:删除Token即可。
  2. 踢用户下线:管理员可以主动清除某用户的Token。
  3. 会话管理:方便地查看当前活跃会话。
  4. 信息实时性:可以随时更新Redis中存储的用户信息,下次请求即生效。

因此,尽管Token+Redis方案在理论上看起来“重”了一些,需要维护Redis的可用性,但它换来的是对会话生命周期的完全掌控,这对于大多数需要严格安全控制和灵活管理能力的生产级应用来说是至关重要的。这或许就是那“80%的项目”做出同样选择的最根本、最现实的原因。技术选型从来不是比谁的理论更酷炫,而是看谁更能扎实、灵活地解决实际问题。

希望这次的对比分析能为你下一次的技术方案决策提供一些参考。关于登录认证和System Design,你还有哪些见解或疑问?欢迎在云栈社区与更多开发者一起交流探讨。




上一篇:网易《星际猎人》品牌焕新分析:国产科幻SLG如何破局长线运营?
下一篇:Struts2 S2-002漏洞分析:从环境搭建到XSS触发原理复现
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-27 20:23 , Processed in 0.396786 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表