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

Nuxt 3中使用useFetch处理401错误、刷新Token并重发请求的最佳方式

在Nuxt 3中用useFetch处理401并自动刷新Token的最佳实践

核心思路

通过封装带认证逻辑的自定义useFetch,拦截401未授权错误,触发Token刷新流程,并重发原请求。同时通过锁机制避免重复刷新,用请求队列处理等待中的并发请求。

实现步骤与代码示例

1. 封装自定义useAuthFetch

这个组合式函数会自动处理Token注入、401拦截、刷新并重发请求:

import { useFetch, useCookie, navigateTo } from '#app'

// 存储Token的Cookie(适配SSR场景)
const accessToken = useCookie('access_token')
const refreshToken = useCookie('refresh_token')
// 防止并发刷新的锁
let isRefreshing = false
// 存储等待重发的请求队列
let failedRequestsQueue = []

export const useAuthFetch = (url, options = {}) => {
  // 给请求头注入当前AccessToken
  const requestHeaders = {
    ...options.headers,
    ...(accessToken.value && { Authorization: `Bearer ${accessToken.value}` })
  }

  return useFetch(url, {
    ...options,
    headers: requestHeaders,
    async onError({ error, retry, options }) {
      // 仅处理401未授权错误
      if (error.response?.status !== 401) return

      if (isRefreshing) {
        // 若正在刷新Token,将当前请求加入队列等待
        return new Promise(resolve => {
          failedRequestsQueue.push(() => resolve(retry()))
        })
      }

      isRefreshing = true
      try {
        // 调用刷新Token接口
        const { data: newTokens } = await useFetch('/api/auth/refresh', {
          method: 'POST',
          body: { refresh_token: refreshToken.value }
        })

        if (!newTokens.value) throw new Error('Token刷新失败')

        // 更新本地Token
        accessToken.value = newTokens.value.access_token
        refreshToken.value = newTokens.value.refresh_token
        // 更新当前请求的Authorization头
        options.headers.Authorization = `Bearer ${newTokens.value.access_token}`
        
        // 重试当前请求
        await retry()
        // 批量重发队列中等待的请求
        failedRequestsQueue.forEach(callback => callback())
        failedRequestsQueue = []
      } catch (refreshError) {
        // 刷新失败,清理Token并跳转登录页
        accessToken.value = null
        refreshToken.value = null
        navigateTo('/login')
      } finally {
        isRefreshing = false
      }
    }
  })
}

2. 在业务代码中使用

直接用useAuthFetch替代原生useFetch即可,无需额外处理认证逻辑:

// 页面/组件中获取用户信息
const { data: userProfile, error } = useAuthFetch('/api/user/profile')

关键注意事项

  • 刷新接口的特殊性:确保/api/auth/refresh接口本身不受401拦截(需允许通过RefreshToken访问)
  • 并发控制:isRefreshing锁避免多个401请求同时触发Token刷新,减少无效接口调用
  • 队列处理:保证Token刷新后,所有之前因401失败的请求都能重新发起,不丢失用户操作
  • 失败降级:刷新Token失败时,必须清理本地Token并跳转登录,避免陷入401死循环

内容的提问来源于stack exchange,提问作者Jakub Rosina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:27:23