axios-auth-refresh 问题

Issue with axios-auth-refresh

我正在尝试通过 React 实现刷新令牌。我正在使用这个库 axios-auth-refresh,它似乎工作得很好,除了一个 API.

// api.js
import Axios from "axios";
import Cookies from 'js-cookie'
import { TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME } from '../constants/constants';
import createAuthRefreshInterceptor from 'axios-auth-refresh';

const api = Axios.create({
    baseURL: process.env.REACT_APP_BACKEND_URL,
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
});

const refreshAuthLogic = async (failedRequest) => {
    const refresh_token = Cookies.get(REFRESH_TOKEN_COOKIE_NAME);
    // if(!refresh_token) return;
    console.log(refresh_token);
    const tokenRefreshResponse = await api.post('auth/createtoken', {
    }, {
        headers: {'Authorization': 'Bearer ' + refresh_token},
        validateStatus: () => true
    });
    console.log(tokenRefreshResponse);
    if(tokenRefreshResponse.data.statusCode === 401 || tokenRefreshResponse.data.statusCode === 403) {
        Cookies.remove(REFRESH_TOKEN_COOKIE_NAME);
        if(!window.location.href.includes('login')) {
            window.location.href = "http://localhost:3000/login";
        }
        return;
    }
    const access_token = tokenRefreshResponse.data.access_token;
    Cookies.set(TOKEN_COOKIE_NAME, access_token, { expires: 60 })
    api.defaults.headers.Authorization = `Bearer ${access_token}`
    failedRequest.response.config.headers['Authorization'] = 'Bearer ' + access_token;
}

// Instantiate the interceptor (you can chain it as it returns the axios instance)
createAuthRefreshInterceptor(api, refreshAuthLogic);

export default api;

如果返回 401,则以下 api 调用不会重复:

const fetchUsers = async () => {
    const { data } = await api.get(`users/`, {params: {tripUsers: true}}, {
      validateStatus: (status) => status !== 401 && status !== 403
    })
    setUsers(data);
  }

  useEffect(() => {
      fetchUsers();
  }, [])

如果返回 401,以下 api 调用会重复:

const fetchProfile = async () => {
        const { data } = await api.get(`/users/${user.userId}`, {}, {
            validateStatus: (status) => status !== 401 && status !== 403
        })

        const {statusCode, message} = data;
        console.log(data);
    
        if(!statusCode) {
            console.log(data);
            setState(data);
        }
    }

    useEffect(() => {
        fetchProfile();
    }, [])

请帮忙。

在这个问题上花了一些时间后,我决定创建一个通用的 API 调用程序,而不是使用 axios 拦截器或任何其他库。这是我的通用 axios API 来电者。它仍然可以改进,但想法是如果第一个令牌已过期,则使用新令牌再次调用 API。

// api.js
import Axios from "axios";
import Cookies from 'js-cookie'
import { TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME } from '../constants/constants';

const api = Axios.create({
    baseURL: process.env.REACT_APP_BACKEND_URL,
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
});

export const callApi = async (method, url, params, other) => {
    const validateStatus = 
        url === 'auth/login' ? () => true : (status) => status !== 401 && status !== 403

    const options = {
        url,
        method,
        validateStatus,
        ...other
    }
    options[method === 'GET' ? 'params' : 'data'] = params;

    console.log(options);

    try {
        const data = await api(options);
        return Promise.resolve(data);
    } catch (err) {
        console.log(err.response.status);
        if (err && err.response && err.response.status === 401) {
            return performTokenRefresh(options);
        } else {
            return Promise.reject(err);
        }
    }
};

const performTokenRefresh = async (options) => {
    const refresh_token = Cookies.get(REFRESH_TOKEN_COOKIE_NAME);
    if(!refresh_token) return {};
    const tokenRefreshResponse = await api.post('auth/createtoken', {
    }, {
        headers: {'Authorization': 'Bearer ' + refresh_token},
        validateStatus: () => true
    });
    if(tokenRefreshResponse.data.statusCode === 401 || tokenRefreshResponse.data.statusCode === 403) {
        Cookies.remove(REFRESH_TOKEN_COOKIE_NAME);
        if(!window.location.href.includes('login')) {
            window.location.href = "http://localhost:3000/login";
        }
        return {};
    }
    const access_token = tokenRefreshResponse.data.access_token;
    Cookies.set(TOKEN_COOKIE_NAME, access_token, { expires: 60 })
    api.defaults.headers.Authorization = `Bearer ${access_token}`
    return api(options);
}

export default api;