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

如何解决Axios拦截器中的无限循环问题

解决Axios拦截器401无限循环问题

原因分析

  1. 刷新请求触发重复拦截:当修改refresh token导致刷新接口返回401时,该请求会被自定义的response拦截器捕获。由于刷新请求的config未设置_retry标记,拦截器会再次调用refreshAccessToken,陷入无限循环。
  2. 失败后未终止错误流程:refreshAccessToken函数在刷新失败时仅返回Promise.reject(error),未执行登出、清空存储和跳转登录页的逻辑,导致错误状态持续,无法终止循环。

解决方法

方法1:在刷新失败时强制终止流程

修改refreshAccessToken函数,在catch块中添加登出和跳转逻辑,确保刷新失败后直接终止所有请求并跳转登录页:

const refreshAccessToken = async () => {
  const refresh_token = localStorage.getItem(REFRESH_TOKEN_KEY);
  if (!refresh_token) {
    store.dispatch(logout());
    localStorage.clear();
    window.location.href = "/";
    return Promise.reject(new Error("无刷新令牌"));
  } else {
    try {
      const response = await axiosInstance.get(REFRESH_TOKEN_ENDPOINT);
      const access_token = response.data.access_token;
      const new_refresh_token = response.data.refresh_token;
      localStorage.setItem(ACCESS_TOKEN_KEY, access_token);
      localStorage.setItem(REFRESH_TOKEN_KEY, new_refresh_token);
      return access_token;
    } catch (error) {
      // 刷新失败直接执行登出逻辑
      store.dispatch(logout());
      localStorage.clear();
      window.location.href = "/";
      return Promise.reject(error);
    }
  }
};

方法2:排除刷新请求的拦截逻辑

在response拦截器中,判断当前请求是否是刷新token的接口,如果是且返回401,直接执行登出逻辑,不再进入重试流程:

axiosInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    const originalRequest = error.config;
    // 拦截刷新token请求的401,直接登出
    if (originalRequest.url === REFRESH_TOKEN_ENDPOINT && error.response?.status === 401) {
      store.dispatch(logout());
      localStorage.clear();
      window.location.href = "/";
      return Promise.reject(error);
    }
    // 处理其他请求的401重试
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        await refreshAccessToken();
        return axiosInstance(originalRequest);
      } catch (error) {
        return Promise.reject(error);
      }
    }
    return Promise.reject(error);
  }
);

方法3:使用原生axios请求刷新接口(推荐)

避免刷新请求触发自定义拦截器,直接用原生axios而非axiosInstance调用刷新接口:

const refreshAccessToken = async () => {
  const refresh_token = localStorage.getItem(REFRESH_TOKEN_KEY);
  if (!refresh_token) {
    store.dispatch(logout());
    localStorage.clear();
    window.location.href = "/";
    return Promise.reject(new Error("无刷新令牌"));
  } else {
    try {
      // 使用原生axios发起刷新请求,绕过自定义拦截器
      const response = await axios.get(`${userEnv.apiUrl}${REFRESH_TOKEN_ENDPOINT}`, {
        headers: {
          Authorization: `Bearer ${refresh_token}`
        }
      });
      const access_token = response.data.access_token;
      const new_refresh_token = response.data.refresh_token;
      localStorage.setItem(ACCESS_TOKEN_KEY, access_token);
      localStorage.setItem(REFRESH_TOKEN_KEY, new_refresh_token);
      return access_token;
    } catch (error) {
      store.dispatch(logout());
      localStorage.clear();
      window.location.href = "/";
      return Promise.reject(error);
    }
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:38:18