Axios拦截器处理Access/RefreshToken时出现无限API调用求助
问题根源分析
当RefreshToken过期时,调用getNewAccessToken()获取新Token的请求会被Axios拦截器捕获,触发新一轮的401错误处理逻辑,进而无限重复调用刷新Token的流程,形成循环。同时,跳转登录的代码执行后未终止当前Promise链,导致错误处理仍持续运行。
修复方案
1. 让刷新Token的请求跳过拦截器
给刷新Token请求添加自定义标识,在拦截器中跳过对该请求的处理,避免递归触发错误逻辑:
修改getNewAccessToken方法:
async getNewAccessToken() { const data = await this.$axios.get("/auth/refresh/token", { // 添加自定义标识,标记此为刷新Token请求 skipInterceptor: true }); return data; }
修改请求拦截器的onSuccess逻辑:
onSuccess: (config: InternalAxiosRequestConfig) => { // 跳过刷新Token请求的拦截处理 if (config.skipInterceptor) { return config; } const accessToken = this.$cookieStorage.getData(COOKIE_KEY.ACCESS_TOKEN); if (!accessToken) { return config; } config.headers.Authorization = `Bearer ${accessToken}`; return config; }
修改响应拦截器的onFailure逻辑,优先判断是否是刷新Token请求本身报错:
onFailure: async (error: any): Promise<any> => { // 若为刷新Token请求返回401,直接执行登出逻辑并终止流程 if (error.config?.url === "/auth/refresh/token" && error.response.status === STATUS.UNAUTHORIZED) { this.$cookieStorage.deleteData(COOKIE_KEY.IS_LOGIN); this.$cookieStorage.deleteData(COOKIE_KEY.USER_INFO); this.$cookieStorage.deleteData(COOKIE_KEY.ACCESS_TOKEN); this.$cookieStorage.deleteData(COOKIE_KEY.REFRESH_TOKEN); window.location.replace("/login"); return Promise.reject(error); } if (error.response.status == STATUS.UNAUTHORIZED) { const { status, data: { accessToken }, } = await this.getNewAccessToken(); if (status === STATUS.UNAUTHORIZED) { this.$cookieStorage.deleteData(COOKIE_KEY.IS_LOGIN); this.$cookieStorage.deleteData(COOKIE_KEY.USER_INFO); this.$cookieStorage.deleteData(COOKIE_KEY.ACCESS_TOKEN); this.$cookieStorage.deleteData(COOKIE_KEY.REFRESH_TOKEN); window.location.replace("/login"); return Promise.reject(error); } if (status === STATUS.OK || status === STATUS.CREATED) { this.$cookieStorage.setData(COOKIE_KEY.ACCESS_TOKEN, accessToken); return this.$axios(error.config); } } return Promise.reject(error); }
2. 修复transformResponse拦截器的onFailure方法
原方法未返回Promise,会导致错误处理异常,修改为:
onFailure(error: AxiosError) { return Promise.reject(error); }
3. 删除重复的响应拦截器注册
构造函数中重复添加了transformResponse拦截器,删除重复代码:
constructor() { this.$axios = BaseApi.createAxios(); const requestInterceptor = this.requestInterceptor(); const responseInterceptor = this.responseInterceptor(); const responseTransform = this.transformResponse(); // 移除下面这行重复代码 // const transformResponse = this.transformResponse(); this.$axios.interceptors.request.use( requestInterceptor.onSuccess, requestInterceptor.onFailure ); this.$axios.interceptors.response.use( responseInterceptor.onSuccess, responseInterceptor.onFailure ); this.$axios.interceptors.response.use( responseTransform.onSuccess, responseTransform.onFailure ); }
额外优化建议
- 添加全局锁变量,防止同时触发多次刷新Token请求,避免并发冲突。
- 在页面组件中增加登录状态判断,状态失效时停止执行API请求逻辑。
内容的提问来源于stack exchange,提问作者Jay Choi
相关产品推荐
相关产品推荐

