You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt 3中REST接口返回401时如何实现全局登录页跳转?

解决Nuxt 3 SSR下Axios全局401跳转问题

针对你遇到的服务端无法通过Axios拦截器跳转登录页的问题,可以通过区分服务端/客户端环境分别处理,结合Axios拦截器和Nuxt全局错误捕获来实现全局401处理:

1. 封装Axios插件,在拦截器中分层处理401

创建plugins/axios.ts,统一配置Axios并处理token刷新及401跳转:

import axios from 'axios'

export default defineNuxtPlugin(() => {
  const api = axios.create({
    baseURL: process.env.API_BASE_URL,
    withCredentials: true
  })

  // 请求拦截:自动携带access token
  api.interceptors.request.use(config => {
    const accessToken = useCookie('access_token').value
    if (accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`
    }
    return config
  })

  // 响应拦截:处理token过期与401
  api.interceptors.response.use(
    res => res,
    async err => {
      const originalRequest = err.config
      // 仅处理未重试过的401请求
      if (err.response?.status === 401 && !originalRequest._retry) {
        originalRequest._retry = true
        try {
          // 尝试用refresh token获取新access token
          const res = await api.post('/refresh')
          const newToken = res.data.accessToken
          // 更新access token cookie
          useCookie('access_token').value = newToken
          // 重发原请求
          originalRequest.headers.Authorization = `Bearer ${newToken}`
          return api(originalRequest)
        } catch (refreshErr) {
          // refresh token失效,执行登录跳转
          // 清除过期token
          useCookie('access_token').value = null
          useCookie('refresh_token').value = null

          if (process.client) {
            // 客户端直接用navigateTo跳转
            await navigateTo('/login')
          } else {
            // 服务端通过响应头重定向
            const event = useRequestEvent()
            if (event) {
              event.res.setHeader('Location', '/login')
              event.res.statusCode = 302
              // 终止响应,避免Nuxt继续渲染页面
              event.res.end()
            }
          }
          // 抛出错误终止Promise链
          return Promise.reject(refreshErr)
        }
      }
      return Promise.reject(err)
    }
  )

  return {
    provide: {
      axios: api
    }
  }
})

2. 全局错误捕获兜底

在app.vue中添加onErrorCaptured钩子,捕获未被Axios拦截器处理的401错误(比如useAsyncData/useFetch在服务端的请求错误):

<template>
  <NuxtPage />
</template>

<script setup>
onErrorCaptured((err) => {
  // 判断是否为401错误
  if (err.response?.status === 401) {
    if (process.client) {
      navigateTo('/login')
    } else {
      const event = useRequestEvent()
      if (event) {
        event.res.setHeader('Location', '/login')
        event.res.statusCode = 302
        event.res.end()
      }
    }
    // 阻止错误继续传播
    return false
  }
  return true
})
</script>

关键注意事项

  • 服务端不能直接用navigateTo:navigateTo是客户端导航API,服务端必须通过设置响应头Location并终止响应来实现重定向。
  • 终止服务端响应:服务端处理401时必须调用event.res.end(),否则Nuxt会继续渲染页面,导致重定向失效。
  • 避免循环请求:给原请求标记_retry属性,防止刷新token失败后重复触发401逻辑。

内容的提问来源于stack exchange,提问作者Bjørn Stenfeldt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:36:19