Axios-刷新令牌循环

时间:2020-06-11 12:16:51

标签: reactjs axios react-hooks interceptor react-context

所以对于axios和上下文来说不是很新,但是我在应用程序级别提供了一个Auth上下文,该上下文由多个子组件使用。在这种情况下,我有一个axios拦截器,它检查对401(未授权)的请求,然后调用刷新令牌api,并将令牌替换为新令牌。我唯一关心的是,第二次调用刷新令牌API时,它会陷入调用刷新令牌api的无尽循环中?任何想法我做错了什么?任何帮助将不胜感激。

AuthContext.js

  axios.interceptors.response.use((response) => {
    return response
  }, function (error) {
    const originalRequest = error.config;

    if (error.response.status === 401 && originalRequest.url ===
      `${BASE_URI}/Identity/Login`) {
      history.push('/login');
      return Promise.reject(error);
    }

    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      const localStorage = JSON.parse(sessionStorage.getItem(AUTH_USER))
      const refreshToken = localStorage.refreshToken;
      return axios.post(`${BASE_URI}/Identity/Refresh`, null,
      {
        headers: {
          'Refresh-Token': refreshToken
        }
      })
      .then(res => {
        if (res.status === 201 || res.status === 200) {
          console.log("In refresh request !")
          console.log(res)
          setSession(null, res.data.token, res.data.refreshToken)
          axios.defaults.headers.common['authorization'] = 'Bearer ' + res.data.token;
          return axios(originalRequest);
        }
      }).catch((error) => {
          console.log("Inside error refresh")
          return Promise.reject(error);
      })
  }
  return Promise.reject(error);
});

2 个答案:

答案 0 :(得分:1)

我做了类似的事情,在token过期时获取refresh token,我也遇到了同样的问题,其实你用的是同一个Axios实例,再创建一个实例

const instance = axios.create();

axios.interceptors.request.use(async (config) => {
    if (token && refreshToken) {
        const data = JSON.parse(atob(token.split('.')[1]));
        const time = Math.floor(new Date().getTime() / 1000);
        if (data.exp < time) {
             instance.defaults.headers.common["Authorization"] = `Bearer ${refreshToken}`;
             const { data } = await instance.get(SERVER.API_ROOT + '/tokens/refresh');
             if (data?.AccessToken) localStorage.setItem(config.AUTH_TOKEN, data.AccessToken)
                else localStorage.clear();
            }
     return config;
}

希望上面的例子对你有帮助

答案 1 :(得分:0)

嘿,我知道这是一个老问题,但您的问题似乎是使用相同的 axios 实例来请求刷新令牌,实际上是创建了一个嵌套的刷新令牌循环。您可以做的是创建一个新的 axios 实例(与初始实例一起,您将同时使用它们)而无需像这样的拦截器:const noInterceptAxios = axios.create();,然后使用它来发送不需要的请求检查访问令牌 return noInterceptAxios.post(`/Identity/Refresh).then().catch()

相关问题