Axios令牌刷新响应拦截器持续触发问题求助
解决Axios拦截器刷新JWT时无限触发的问题
你遇到的无限循环问题,核心原因是刷新token的请求本身也会经过响应拦截器,当Cookie无效导致刷新请求返回401时,拦截器会再次触发刷新逻辑,形成闭环。再加上几个细节没处理到位,才导致了这个问题,我一步步给你梳理调整方案:
核心问题拆解
- 你的
/auth刷新请求没有被排除在拦截器逻辑之外,一旦它返回401,就会重复触发刷新流程 - 原代码里的
_retry标记只加在了失败的原请求上,但刷新请求本身没有这个标记,拦截器会对它重复执行逻辑 - 要注意
dispatch的作用域:确保拦截器能正确访问到Redux的dispatch,不然刷新成功后无法更新本地的auth状态
修改后的代码方案
1. 调整刷新token的函数
给刷新请求加个专属标识,方便后续拦截器识别并跳过它:
function refreshToken(dispatch) { // 标记这是刷新请求,避免被拦截器重复处理 const refreshRequestConfig = { url: '/auth', method: 'put', _isRefresh: true }; return new Promise((resolve, reject) => { instance.request(refreshRequestConfig) .then((response) => { dispatch({ type: "UPDATE_AUTH", payload: response.data }); // 刷新成功后记得更新Axios实例的默认Authorization头 instance.defaults.headers.common['Authorization'] = `Bearer ${response.data.token}`; resolve(response); }) .catch((error) => { // 刷新失败可以做些清理,比如清空本地auth状态 dispatch({ type: "CLEAR_AUTH" }); reject(error); }); }); }
2. 修复响应拦截器逻辑
重点是排除刷新请求,并且确保每个失败请求只触发一次重试:
instance.interceptors.response.use( response => response, err => { const error = err.response; // 如果没有响应或者不是401状态,直接抛出错误 if (!error || error.status !== 401) { return Promise.reject(error); } const originalRequest = err.config; // 1. 跳过刷新请求,避免循环触发 if (originalRequest._isRefresh) { return Promise.reject(error); } // 2. 如果已经重试过,直接抛出错误 if (originalRequest._retry) { return Promise.reject(error); } // 标记该请求已进入重试流程 originalRequest._retry = true; // 刷新token后重试原请求 return refreshToken(dispatch) .then(() => instance(originalRequest)) .catch((e) => Promise.reject(e)); } );
额外注意事项
- 刷新成功后一定要更新Axios实例的默认Authorization头,不然重试的原请求还是会带旧的过期token
- 确保拦截器能访问到
dispatch:如果是React+Redux环境,可以把拦截器放在store初始化之后,或者用useDispatch钩子获取(注意函数组件的作用域问题)
这样调整后,就能彻底避免刷新请求触发拦截器导致的无限循环,同时保证重试逻辑的健壮性。
内容的提问来源于stack exchange,提问作者mallix
相关产品推荐
相关产品推荐

