Vue 前端请求拦截器统一处理 401 跳转登录页怎么实现?

文章导读
在 Vue 项目中,最稳妥的做法是在 Axios 响应拦截器中判断状态码 401,清除本地 token 并跳转登录页,但必须排除登录接口本身以避免死循环,同时需处理并发请求导致的多次跳转问题。
📋 目录
  1. 核心代码实现
  2. 配置步骤
  3. 怎么验证是否生效
  4. 常见坑与排查
A A

在 Vue 项目中,最稳妥的做法是在 Axios 响应拦截器中判断状态码 401,清除本地 token 并跳转登录页,但必须排除登录接口本身以避免死循环,同时需处理并发请求导致的多次跳转问题。

先说结论:拦截器处理是标准方案,重点在于防止重复跳转和登录接口误判。

  • 适合单页应用(SPA)及需要统一鉴权的场景
  • 先看登录接口是否也会返回 401,需做白名单豁免
  • 建议增加防抖标志位,避免并发请求触发多次跳转

核心代码实现

以下是一个包含白名单判断和防抖处理的完整 Axios 拦截器示例。请注意,必须正确引入 router 实例,否则跳转逻辑无法生效。

import axios from 'axios'
import router from '@/router' // 关键:引入路由实例,路径根据项目结构调整

const loginPath = '/login' // 定义登录页白名单路径
let isReloginShow = false // 防抖标志位,防止并发请求多次跳转

axios.interceptors.response.use(response => {
  return response
}, error => {
  if (error.response && error.response.status === 401) {
    const { config } = error
    
    // 1. 白名单判断:如果是登录接口本身失败,不触发跳转,避免死循环
    if (config.url.includes(loginPath)) {
      return Promise.reject(error)
    }
    
    // 2. 防抖判断:如果正在跳转中,后续 401 请求不再重复触发
    if (isReloginShow) {
      return Promise.reject(error)
    }
    
    isReloginShow = true
    
    // 3. 清除本地缓存 token 及用户信息
    localStorage.removeItem('token')
    // 如果使用了 Vuex/Pinia,建议同时清除 store 中的用户状态
    // store.commit('CLEAR_USER_INFO') 
    
    // 4. 跳转登录页
    router.push('/login')
    
    // 5. 重置标志位(可选):防止跳转后新请求无法再次触发逻辑
    setTimeout(() => { isReloginShow = false }, 5000)
  }
  return Promise.reject(error)
})

这段代码需要放在项目初始化阶段(如 main.js 或专门的 request.js 文件中),确保所有请求都经过此拦截器。

配置步骤

1. 确认路由实例:检查项目中 router 实例的导出路径,通常在 @/router/index.js,确保拦截器文件中能正确 import。

Vue 前端请求拦截器统一处理 401 跳转登录页怎么实现?

2. 编写拦截逻辑:将上述代码复制到请求封装文件中,替换原有的简单拦截逻辑。

3. 配置白名单:根据实际后端接口定义,修改 loginPath 变量,确保登录接口 URL 匹配准确。

4. 处理并发跳转:代码中已内置 isReloginShow 标志位,无需额外配置,但需确保该变量作用域全局唯一。

5. 清理缓存:跳转前务必清除本地存储的 token 及用户信息,防止刷新后依旧携带旧 token。

怎么验证是否生效

1. 模拟过期:登录成功后,手动在浏览器 Application 面板中删除 token,或者等待 token 自然过期。

Vue 前端请求拦截器统一处理 401 跳转登录页怎么实现?

2. 触发请求:刷新页面或点击一个需要鉴权的按钮。

3. 观察网络:打开开发者工具 Network 标签,确认请求返回状态码为 401。

4. 检查跳转:确认页面 URL 变更为登录页,且本地存储中已无 token。

5. 测试登录接口:在登录页故意输入错误密码,确认不会跳转回登录页(即不会死循环),而是显示后端返回的错误消息。

Vue 前端请求拦截器统一处理 401 跳转登录页怎么实现?

常见坑与排查

1. 死循环跳转:登录接口本身鉴权失败返回 401,被拦截器捕获又跳回登录页。解决:必须在拦截器中判断请求 URL,登录接口不走 401 跳转逻辑(见代码白名单部分)。

2. 路由实例未找到:代码运行报错 Cannot read property 'push' of undefined解决:检查 import router 路径是否正确,确保引入的是已初始化的 router 实例而非配置对象。

3. 多次弹窗:有些项目会在 401 时弹出提示框。如果没有防抖处理,并发请求会导致弹出多个提示框。解决:统一在拦截器里处理提示,或利用 isReloginShow 限制提示频率。

4. 静默刷新遗漏:部分项目采用 token 静默刷新机制。如果实现了刷新逻辑,401 拦截器需要先尝试刷新 token,刷新失败后再跳转登录,不要一遇到 401 就立刻踢用户。