在 Vue 3 结合 Axios 1.6.0 的项目中,通过响应拦截器判断 error.response.status === 401 可触发令牌刷新,典型实现能将用户无感知的中断时间控制在 200ms 以内。
原因分析
HTTP 状态码 401 Unauthorized 定义于 RFC 7235 第 3.1 节,表示请求缺乏有效的身份验证凭证。在 JWT 机制中,Access Token 通常设定较短有效期(如 2 小时),过期后服务端返回 401。若前端未拦截处理,用户会直接被踢出登录态。根据 Axios 官方文档,响应拦截器是处理此类全局错误的标准入口,错误对象结构固定为 error.response.status。
解决方案
1. 配置 Axios 响应拦截器
在 src/utils/request.js 中注册拦截器,监听 status 是否为 401。参考 Axios 1.6.0 版本 API,代码示例如下:
service.interceptors.response.use(response => { return response }, error => { if (error.response && error.response.status === 401) { handleUnauthorized() } return Promise.reject(error) })
2. 实现无感刷新逻辑
核心是防止并发请求重复刷新。需维护一个 isRefreshing 标志位和一个 requestQueue 队列。当第一个 401 触发刷新时,isRefreshing 设为 true,后续请求存入队列。刷新成功后(通常耗时 100-300ms),遍历队列重试。若刷新失败(如 Refresh Token 也过期),则状态码仍为 401,此时应清除本地存储并跳转登录页。
3. 路由守卫配合
使用 Vue Router 4.2.5 的 beforeEach 守卫,在跳转前检查 Token 有效性。若拦截到 401 且刷新失败,调用 router.replace('/login') 强制重新认证,避免死循环。
注意事项
1. 无限刷新循环:若刷新接口本身返回 401,必须标记不再尝试刷新,否则会导致浏览器卡死。社区反馈常见错误是未在 refresh 请求中排除拦截逻辑。
2. 并发请求丢失:未使用队列机制时,5 个并发请求同时 401 会触发 5 次刷新接口,导致服务端报错 429 Too Many Requests。
3. 存储安全:JWT 建议存储在 httpOnly Cookie 中而非 localStorage,防止 XSS 攻击窃取令牌,这是 OWASP 建议的安全实践。
参考来源
来源:Axios GitHub - Interceptors 官方文档说明
来源:MDN Web Docs - HTTP Status 401 定义
来源:Vue Router Docs - Navigation Guards 使用指南
原文链接:https://www.zjcp.cc/ask/9635.html
