前后端身份认证:JWT黑名单与刷新令牌轮转

Oliver
Oliver
发布时间:2026-09-09 | 3人浏览过
原创

认证架构与令牌生命周期设计

访问令牌(Access Token)用于短期鉴权,通常有效期设为15至30分钟,前端可暂存于内存或HttpOnly Cookie,后端通过非对称验签直接放行。刷新令牌(Refresh Token)用于长期维持会话,有效期可达数天至数周,必须严格存储于HttpOnly、Secure、SameSite=Strict的Cookie中,仅用于向后端换取新Access Token。完整流程为:前端提交凭证至认证服务,服务签发双令牌;后续请求携带AT访问资源,AT过期返回401;前端拦截401后携带RT请求刷新接口,后端验证RT后下发新AT。JWT的无状态特性使其优势在于无需查库即可验签,但正因如此,JWT一旦签发便无法在服务端主动撤销。若用户修改密码或主动注销,旧JWT在自然过期前依然有效,因此必须引入外部状态机制(如黑名单或短有效期+轮转)来弥补这一局限。

JWT黑名单:实现主动注销与紧急吊销

黑名单机制适用于用户主动登出、修改密码或检测到异常登录等需立即阻断会话的场景。实现时,JWT载荷中必须包含全局唯一标识jti(JWT ID)。当触发注销或吊销时,后端提取该jti写入Redis,键名格式如jwt:blacklist:{jti},并将过期时间精确设置为该JWT剩余的TTL(Time-To-Live),避免永久占用内存。后端校验逻辑应置于网关层或全局拦截器中,在验签通过后、业务逻辑执行前,优先查询Redis是否存在该jti,若存在则直接拒绝请求并返回401。引入黑名单打破了JWT的无状态性,增加了存储与网络开销。为控制成本,需依赖Redis的自动过期机制实现零人工清理,同时可结合定期扫描脚本清理异常残留键,确保状态管理轻量化且高效。

该节需要一张真实的Redis或JWT黑名单实现示意配图,体现token吊销、jti查询和TTL过期过程。
FastAPI注销流程图展示服务端校验JWT后,将Access Token和Refresh Token的JTI加入Redis黑名单并清理会话。

刷新令牌轮转:防止Refresh Token重放

刷新令牌轮转(Rotation)的核心在于“一次一换”:每次客户端携带Refresh Token请求刷新时,服务端在签发新RT的同时,立即将旧RT标记为失效。为防御重放攻击,系统需引入Token Family概念,即同一会话下的所有RT共享一个家族ID。若服务端发现某个已失效的RT被再次使用,即可判定为令牌泄露或恶意重放,此时不仅拒绝请求,还会立即吊销该家族下的所有令牌,强制用户重新登录。针对并发刷新场景,后端需采用数据库乐观锁或Redis分布式锁保证原子性,避免同一RT被多次成功刷新。对于网络抖动导致的重复请求,服务端应返回幂等响应或缓存最近一次签发结果。该机制虽增加了状态维护成本,但能有效遏制RT泄露后的横向扩散,是OAuth 2.1推荐的最佳实践。

该节需要一张真实的Refresh Token Rotation流程配图,清晰展示旧令牌失效、新令牌签发以及重放检测后的家族吊销。
Refresh Token轮转与重放检测流程展示旧令牌失效、新令牌生成,以及检测到重放后吊销整个令牌家族。

前后端落地、验证与常见避坑

前端落地需通过Axios拦截器捕获401响应,自动挂起后续请求并发起刷新调用,成功后重试原请求队列;若刷新失败则跳转登录页。后端需严格分离AT与RT校验逻辑:AT仅验签与查黑名单,RT则需查库比对哈希值、校验轮转状态与家族关系。验证阶段应覆盖完整链路:正常登录获取双令牌、AT过期自动刷新、主动注销触发黑名单、RT过期拒绝刷新、重放旧RT触发家族吊销,以及高并发下的刷新竞态测试。常见高风险坑点包括:将RT存入LocalStorage易受XSS窃取,需改用HttpOnly Cookie;刷新接口若未配置CSRF防护易遭跨站伪造;日志中明文打印完整Token会导致泄露;轮转时若未加锁会引发“竞态条件”导致多客户端状态不一致。严格遵循最小权限与安全存储原则,方能构建健壮的认证体系。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表