简体   繁体   English

使用 Axios 请求拦截器(interceptors.request)刷新 JWT Token - 一次多个请求问题

[英]Refresh JWT Token using Axios request interceptor (interceptors.request) - Multiple requests at once problem

I'm using this code to intercept every HTTP call in Axios, in order to keep the user logged in by refreshing the JWT token when it expires:我正在使用此代码拦截 Axios 中的每个 HTTP 调用,以便通过在 JWT 令牌过期时刷新来保持用户登录:

const { token } = window.localStorage;

const axiosInstance = axios.create({
    baseURL: process.env.VUE_APP_API_ENDPOINT,
    withCredentials: false,
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: token && token.length > 0 ? `Bearer ${token}` : ""
    }
  });

axiosInstance.interceptors.request.use(request => {
    if (request.url.endsWith("refresh")) {  // prevent infinite loop
      return request;
    }

const { expiryDate } = window.localStorage;
const currentTimestamp = Math.round(new Date().getTime() / 1000);

if (expiryDate && currentTimestamp >= expiryDate) {
  console.log("token expired.");

  return store
    .dispatch("auth/refreshToken")  // refreshToken action will place the token in localStorage.token
    .then(() => {
      const newToken = window.localStorage.token; 

      request.headers.Authorization = `Bearer ${newToken}`;

      return Promise.resolve(request);
    })
    .catch(() => Promise.resolve(request));
}
console.log("token not expired.");

return request;

});

This used to work fine until I added more requests at page load, each request is trying to refresh the token which causes an error in the back-end.这曾经很好用,直到我在页面加载时添加了更多请求,每个请求都试图刷新令牌,这会导致后端出错。 How do I solve this problem?我该如何解决这个问题? I have searched a lot but all the solutions I found were for interceptors.response like this one , I'd like to use interceptors.request because logging in is optional and there will be no 401 response if the user is not logged in.我搜索了很多,但我找到的所有解决方案都是针对interceptors.response 这样的,我想使用interceptors.request因为登录是可选的,如果用户未登录,则不会有401响应。

EDIT: Based on the answer from User 28 below the code has changed to:编辑:根据下面用户 28 的回答,代码已更改为:

axiosInstance.interceptors.request.use(async config => {
    if (config.url.endsWith("refresh")) {
      // if we are making a refresh token call, return it to prevent infinite loop
      return config;
    }

    await axiosInstance.refreshingToken;

    const { expiryDate } = window.localStorage; // token expiry date

    const currentTimestamp = Math.round(new Date().getTime() / 1000);

    if (expiryDate && currentTimestamp >= expiryDate) {
      axiosInstance.refreshingToken = store.dispatch("auth/refreshToken"); // this will update the token in localstorage
      await axiosInstance.refreshingToken;
    }

    const { token } = window.localStorage; // grab the token from localstorage

    config.headers.Authorization = `Bearer ${token}`;

    return config;
  });

You need a global variable to determine you have to wait or not.您需要一个全局变量来确定是否必须等待。 The easiest way is to assign it to the axios instance.最简单的方法是将其分配给 axios 实例。

Example Code:示例代码:

axios.interceptors.request.use(async config => {
  if (isRefreshTokenRequest) {
    return config
  }

  if (axios.refreshingToken) {
    await axios.refreshingToken
  }

  if (isTokenExpired) {
    axios.refreshingToken = store.dispatch('auth/refreshToken')
    await axios.refreshingToken
  }

  // set authorization header

  return config
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM