React调用DRF的/token/refresh返回401 unauthorized报错,控制台出现大量错误
问题根因分析
- 无限循环重试:没有给已经尝试过刷新token的请求加标记,当刷新token的请求本身返回401时(比如refresh token过期、无效),会重新触发拦截器逻辑,反复调用刷新接口,形成死循环,最终产生数千条报错
- 判断逻辑错误:现有代码中
&& 'access_token'是恒为真的字符串字面量判断,完全没有起到过滤重复请求的作用 - 刷新失败无兜底:refresh接口调用失败后仅打印日志,没有清理过期token、终止循环的逻辑,会导致无效请求反复发送
- 初始化头设置不合理:创建axios实例时就读取localStorage的access_token,如果页面初始化时用户还未登录、或者token已过期,初始的Authorization头就是错误值
修复方案
修复后的完整代码如下:
const axiosInstance = axios.create({ baseURL:'http://localhost:8000/api', timeout: 5000, headers: { 'Content-Type': 'application/json', 'accept': 'application/json' } }) // 新增请求拦截器,每次请求动态读取最新的token,避免初始化时token失效问题 axiosInstance.interceptors.request.use( config => { const accessToken = localStorage.getItem('access_token') if (accessToken) { config.headers.Authorization = `Bearer ${accessToken}` } return config }, error => Promise.reject(error) ) axiosInstance.interceptors.response.use( response => response, error => { const originalRequest = error.config; // 新增_retry标记,同一个请求仅尝试刷新一次token,避免死循环 if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true const refreshToken = localStorage.getItem('refresh_token'); // 没有refreshToken直接走失败逻辑,清空存储跳登录 if (!refreshToken) { localStorage.clear() // 可替换为你的项目登录跳转逻辑,比如react-router的navigate('/login') window.location.href = '/login' return Promise.reject(error) } return axiosInstance .post('/token/refresh/', {refresh: refreshToken}) .then((response) => { localStorage.setItem('access_token', response.data.access); localStorage.setItem('refresh_token', response.data.refresh); originalRequest.headers['Authorization'] = "Bearer " + response.data.access; return axiosInstance(originalRequest); }) .catch(err => { console.log(err) // 刷新失败说明refreshToken也失效,清空存储跳登录 localStorage.clear() window.location.href = '/login' return Promise.reject(err) }); } return Promise.reject(error); } );
内容的提问来源于stack exchange,提问作者silviaa11
相关产品推荐
相关产品推荐

