无感知刷新 Token 的核心是拦截 401 响应后用 Refresh Token 获取新 Access Token 并重放请求:通过刷新锁(refreshingPromise)与 Promise 队列避免并发刷新,Refresh Token 存于 httpOnly Cookie,Access Token 存内存,刷新失败则登出,主动预刷新可减少 401。

无感知刷新 Token 的核心是:在请求因 Token 过期被拒绝(如返回 401)时,自动用 Refresh Token 换取新 Access Token,并重放原始请求,整个过程对用户和业务逻辑透明。
拦截 401 响应并触发刷新
所有 Ajax 请求统一走一个封装的请求函数(如基于 fetch 或 axios),在响应拦截器中判断状态码:
- 遇到
401且当前没有正在进行的刷新任务,就暂停后续请求、发起刷新 Token 请求 - 若已有刷新进行中,则让新请求等待刷新完成后的结果,避免并发多次刷新
- 刷新成功后,更新本地存储的 Access Token,并重试原请求;失败则跳转登录页
用 Promise 队列管理重试请求
刷新过程是异步的,多个同时失败的请求不能各自发刷新请求。推荐用一个“刷新锁” + 请求队列:
- 定义一个
let refreshingPromise = null标记是否正在刷新 - 当首次 401 到来,调用
refreshToken()并赋值给refreshingPromise - 后续 401 请求都
await refreshingPromise,复用同一结果 - 刷新完成后清空
refreshingPromise,供下次使用
安全存储与传递 Token
Access Token 通常存在内存或 sessionStorage 中(不存 localStorage 防 XSS);Refresh Token 建议存在 httpOnly Cookie 中(后端设置),前端无法直接读取,但会随请求自动携带:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- 刷新接口(如
/auth/refresh)只需发送凭证(如 Cookie),无需前端暴露 Refresh Token - 新 Access Token 由后端通过响应头(如
X-Auth-Token)或响应体返回,前端提取后更新内存状态 - 所有后续请求自动带上新 Token(例如通过请求拦截器注入
Authorization头)
避免循环刷新与过期边界处理
Token 刷新不是万能的,需防止无限重试或已彻底失效的情况:
- 刷新接口本身也返回 401 或 403,说明 Refresh Token 已失效(过期/被撤销),应立即登出
- 为防止重放请求再次失败,可加简单计数或时间戳标记,单个请求最多重试一次
- 前端可缓存 Token 过期时间(
expires_in),在到期前 60 秒主动刷新,减少 401 触发频率
不复杂但容易忽略细节,关键是把错误处理、状态同步和请求调度串成闭环。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










