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

React项目中Axios调用刷新令牌接口返回401错误的解决咨询

排查并解决Axios调用刷新令牌接口返回401的问题

问题背景

在Windows 10环境下使用react-router-dom 5.2.0、react-redux 7.2.5、React 17.0.2、axios 0.21.4开发图片上传功能时,调用/api/v1/users/token/refresh/接口返回401错误,该问题在封装axiosInstance箭头函数后出现,怀疑问题出在axiosInstance.js文件中。

相关代码

axiosInstance.js

import jwt_decode from 'jwt-decode';
import dayjs from 'dayjs';
import axios from 'axios';
import {updateAccessToken} from '../actions/userActions';
const baseURL = 'http://127.0.0.1:8000';

const axiosInstance = (userInfo , dispatch) => {
    const instance = axios.create({
        'mode': 'cors',
        baseURL,
        headers: {
            'Content-Type': 'application/json',
            Authorization:`Bearer ${userInfo?.access}`,
        }
    });
    instance.interceptors.request.use(async req=> {
        try {
        const user = jwt_decode(userInfo.access);
        const isExpired = dayjs.unix(user.exp).diff(dayjs()) < 5000;
        if (!(isExpired)) {
            return req
        }

            const response = await axios.post(
                '/api/v1/users/token/refresh/' , {refresh:userInfo.refresh},
            );


        dispatch(updateAccessToken(response.data))
        req.headers.Authorization = `Bearer ${response.data.access}`;
        return req;
        } catch (error) {
           console.log(error)
        }
    });
    return instance
}

export default axiosInstance;

userActions.js

export const userFurtherInformationAction = (image, gender) => async (dispatch, getState) => {
    try {
        dispatch({ //USER FURTHER INFORMATION REQUEST
            type: USER_FURTHER_INFORMATION_REQUEST,

        });
        const {userLogin: {userInfo}} = getState();
        const formData = new FormData();
        const image_url = URL.createObjectURL(image)

        formData.append('userPicture', image);
        formData.append('sex', gender);

        const authRequestAxios = axiosInstance(userInfo,dispatch);
        const {data} = await authRequestAxios.post('/api/v1/users/complete_user_further_info/', formData);

        dispatch({ //USER FURTHER INFORMATION SUCCESS
            type: USER_FURTHER_INFORMATION_SUCCESS, payload: data,

        });
        localStorage.setItem('userInfo', JSON.stringify(data));
    } catch (error) {
        dispatch({ // USER FURTHER INFORMATION FAILED
            type: USER_FURTHER_INFORMATION_FAILED,
            payload: error.response && error.response.data.detail ? error.response.data.detail : error.message,
        });
    }
}

问题排查

  • 刷新接口地址错误:拦截器中调用刷新令牌接口时,直接使用axios.post('/api/v1/users/token/refresh/'),未拼接预设的baseURL,导致请求发送到前端项目域名而非后端API域名,后端无法识别请求返回401。
  • 拦截器异常处理缺失:catch块捕获错误后未抛出异常,会导致请求带着过期token继续发送,引发401。
  • Content-Type冲突:axiosInstance默认设置Content-Type: application/json,但上传接口使用FormData,该配置会导致后端无法解析请求,间接引发认证类错误。
  • refresh令牌有效性存疑:userInfo.refresh可能存在过期、格式错误或未正确存储的情况。

修复方案

1. 修正刷新接口请求地址

使用已创建的axios实例发送刷新请求,自动携带baseURL:

// 替换原axios.post为instance.post
const response = await instance.post(
    '/api/v1/users/token/refresh/' , {refresh: userInfo.refresh}
);

2. 完善拦截器异常处理

在catch块中抛出错误,确保上层能捕获并处理:

catch (error) {
    console.log(error);
    return Promise.reject(error);
}

3. 适配FormData请求的Content-Type

移除axiosInstance中固定的Content-Type配置,axios会自动识别FormData并设置正确的multipart/form-data:

const instance = axios.create({
    'mode': 'cors',
    baseURL,
    headers: {
        Authorization:`Bearer ${userInfo?.access}`,
    }
});

4. 验证refresh令牌有效性

在调用刷新接口前打印userInfo.refresh的值,确认其未过期、格式符合后端要求,且正确从Redux或localStorage中获取。

修复后的完整axiosInstance.js

import jwt_decode from 'jwt-decode';
import dayjs from 'dayjs';
import axios from 'axios';
import {updateAccessToken} from '../actions/userActions';
const baseURL = 'http://127.0.0.1:8000';

const axiosInstance = (userInfo , dispatch) => {
    const instance = axios.create({
        'mode': 'cors',
        baseURL,
        headers: {
            Authorization:`Bearer ${userInfo?.access}`,
        }
    });
    instance.interceptors.request.use(async req=> {
        try {
            const user = jwt_decode(userInfo.access);
            const isExpired = dayjs.unix(user.exp).diff(dayjs()) < 5000;
            if (!isExpired) {
                return req;
            }

            const response = await instance.post(
                '/api/v1/users/token/refresh/' , {refresh: userInfo.refresh}
            );

            dispatch(updateAccessToken(response.data));
            req.headers.Authorization = `Bearer ${response.data.access}`;
            return req;
        } catch (error) {
            console.log(error);
            return Promise.reject(error);
        }
    });
    return instance;
}

export default axiosInstance;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:42:51