使用 JWT 时为什么还需要 Redis 白名单?

考查重点:无状态令牌与实时撤销。JWT 不自动反映退出/封禁,Redis 白名单让在线授权可撤销;每请求校验令牌与名单,权衡可用性与成本

本题目录

参考答案

核心回答

JWT 的签名和声明校验可以确认令牌是否可信、是否在有效期内,但它不会自动知道用户刚刚退出、被踢下线或账号被禁用。Redis 白名单保存当前仍被允许的令牌或会话:请求既要通过 JWT 校验,也要命中有效的允许记录;注销时删除相应记录,后续请求即使携带尚未到期的 JWT,也会被拒绝。

因此,JWT 负责携带可验证的身份声明,Redis 补充服务端的在线状态与撤销控制。这样可以实现主动失效和多端会话管理,但每次校验增加了状态查询与 Redis 依赖,整个认证方案也就不再是完全无状态。是否需要白名单,取决于是否要求及时撤销,以及能否接受这些成本。

为什么清掉客户端 JWT 还不够

假设客户端持有一个尚未过期的有效 JWT。点击退出后,浏览器清除本地凭据,只能保证该客户端以后不再主动携带它;其他设备、窗口或已经复制走的令牌仍可能继续被使用。若服务端只检查签名与 exp,令牌通常会有效到过期,除非另有撤销或密钥策略。

Redis 白名单把“曾经签发且仍有效”和“此刻仍被允许”分开。登录时登记允许记录,退出、封禁或踢人时删除或停用它,后续认证检查相应状态。这里的在线表示服务端认可该会话,并不证明用户正坐在设备前,也不等于浏览器连接始终存在。

一个参考流程

登录时验证用户身份,生成包含用户标识、签发方、接收方、到期时间和唯一令牌标识的 JWT,并建立允许记录。可以按 jti 保存对应用户、会话和有效期,也可以设计会话标识与版本来管理一组令牌;不一定要把完整 JWT 原文作为 Redis 的值。建立会话状态失败时,不应仍返回一个宣称已经完成登录、却无法正常使用的令牌。

请求时先用成熟组件校验固定允许的签名算法、可信密钥以及应用要求的 iss、aud、exp、nbf 等声明,再按已验证的标识查允许记录,核对用户、会话、状态与适用范围。最后仍要对本次访问的资源和动作鉴权。令牌有效和会话在线,都不代表它可以访问任意资源。

注销时撤销相应会话或令牌记录,并清除客户端凭据。如果存在 refresh token 或其他刷新授权,也要按退出范围撤销,否则旧 access token 虽已失效,客户端仍可能换出新令牌。刷新与注销并发时,应检查会话版本或撤销状态,避免刷新操作把已经退出的会话重新建立起来。

白名单设计中的几个取舍

有效期不能只靠 Redis TTL

JWT 自带的 exp 仍要验证。延长 Redis 记录的 TTL,不会修改已签名令牌里的到期时间;到期后需要按刷新策略签发新令牌。反过来,Redis 记录提前过期或被删除,会使尚未到期的 JWT 提前失去允许状态,这可以是会话策略的一部分,也可能是缓存淘汰造成的异常登出。

按令牌保存记录时,可根据令牌剩余寿命与会话策略设置 TTL;按会话保存时,则要区分会话寿命与单个 access token 寿命。二者采用哪个更短的限制,要由认证规则决定,不能出现“Redis 有记录就忽略 JWT 已过期”。

多窗口、多设备怎样退出

共用同一会话的多个窗口,会受到同一次撤销影响;使用独立会话的手机与浏览器,则可以只退出当前设备。若要求全部退出,可以维护用户的会话索引逐个撤销,或校验用户级会话版本,让旧版本令牌失效。

服务端拒绝旧会话,与前端立即显示退出是两件事。前端可以通过窗口间同步或服务端通知更新界面,也可以在后续请求收到认证失败后清理界面;真正的访问控制仍在服务端。具体退出范围要与产品约定一致。

Redis 不可用与状态一致性

白名单是认证依据,查询失败与“查不到记录”应区分。查不到有效记录按未授权处理;Redis 超时则说明当前无法确认会话状态,受保护操作通常应拒绝或返回服务暂不可用,不能无条件绕过检查,让刚撤销的令牌重新可用。

若用本地缓存减少查询,需要明确撤销传播和缓存失效时间;存在缓存或副本延迟时,“删除 Redis 记录后立即全局失效”就未必成立。还应关注认证数据的淘汰、故障恢复与旧状态回流,避免把会话控制数据按普通可丢弃缓存随意处理。

白名单、黑名单和短令牌怎样选择

白名单记录仍被允许的会话,缺少记录就拒绝,适合会话管理与主动下线;黑名单只记录已撤销令牌,请求在签名等校验通过后,还需确认没有被撤销。两者的存储规模与故障行为不同:白名单记录丢失通常导致误登出,黑名单记录丢失则可能让已撤销令牌被再次接受。

短期 access token 加受控的刷新机制,可以缩短令牌暴露窗口、减少一部分在线查询,但若资源服务不查询撤销状态,通常仍要接受 access token 在剩余有效期内继续可用的窗口。它并不天然等同于立即注销。

如果每次请求本来都要查 Redis,而系统不需要跨服务验证签名声明,随机的不可猜测令牌加服务端会话也值得考虑。JWT 加 Redis 的意义可以是统一声明格式、跨服务传递与会话控制的组合,不能只以“JWT 无状态”作为全部选型理由。

常见追问

把用户 ID 放进 Redis,存在就放行,可以吗?

这只能表示用户级允许状态,未必能区分同一用户的多台设备、旧令牌和新令牌。需要按退出范围选择令牌、会话或用户版本粒度,并核对令牌与记录的绑定。否则一个旧 JWT 可能借用另一次新登录建立的用户记录继续访问。

有白名单,还需要验证 JWT 签名吗?

需要。白名单补充在线状态,不替代来源、完整性、有效期和使用范围校验。也不能仅对 JWT 解码后就信任其中的用户或权限;常见的签名 JWT 载荷可被读取,签名本身不提供内容保密。

参考资料

  • 国内:JavaGuide:JWT 结构与登录鉴权:借鉴解析与验证、声明及登录流程的说明,解释正文中读取载荷与可信接受 JWT 的区别,以及白名单之外仍需完成的安全校验。
  • 国内:JavaGuide:JWT 身份认证优缺点分析:注销、服务端存储、黑名单和刷新授权部分,解释主动失效需求为什么会重新引入状态,以及方案的查询成本与取舍。
  • 国内:Sa-Token:和 JWT 集成:不同模式对 Redis 会话、注销和踢下线能力的区别,提供“JWT 格式相同、会话控制能力仍不同”的实现例子;使用框架时需核对具体模式和版本。
  • 国外:RFC 7519:JSON Web Token:exp、nbf、aud 与 jti 的定义说明令牌有效期、使用方和唯一标识,帮助设计允许记录及其与令牌的绑定。
  • 国外:RFC 8725:JWT Best Current Practices:算法、签发方、接收方和声明验证要求,说明为何 Redis 命中不能取代 JWT 的安全校验,也不能直接信任未验证的载荷。

相关面经

3 篇

汇川技术

全栈开发工程师
查看原面经 →
JWT的流程是什么,为什么要用Redis存JWT

靖安科技

后端工程师(RAG/Agent 项目)
秋招一面
查看原面经 →
追问
用户退出后,原来的 JWT 会自动失效吗

科大讯飞

Java 开发工程师
秋招一面、二面
查看原面经 →
用jwt为什么还要做redis的白名单

相关题目

4 题