当前位置: 首页 > 知识库问答 >
问题:

React axios拦截器以获取刷新令牌

岳泉
2023-03-14

我有一个使用express api的react应用程序。我正在尝试在访问令牌过期时刷新令牌。我正在使用axios拦截器来实现这一成就。

let isRefreshing = false;
let failedQueue = [];

const processQueue = (error, accessToken = null) => {
  failedQueue.forEach((prom) => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(accessToken);
    }
  });

  failedQueue = [];
};

axiosInstance.interceptors.response.use(
  async (response) => {
    return response;
  },
  async (error) => {
   
    const { status, data } = error.response;
    const originalRequest = error.config;  
    if (error.response.status===401 && data.message === "Invalid refresh token") {
        console.log("unauthorized");
       store.dispatch(authActions.logout());
        return;
      }
      
      if(error.response.status === 401 && data.message === "You are not authorized to access this route,you don't have a valid refresh token to create new access token "){
        console.log("invalid refresh token");
        console.log(error.response)
        store.dispatch(authActions.logout());
        return error.response;
      }

      if (error.response.status === 401 && !originalRequest._retry) {
        if (isRefreshing) {
          console.log("isRefreshing");
          return new Promise((resolve, reject) => {
            console.log("isRefreshing2");
            failedQueue.push({ resolve, reject });
          })
            .then((accessToken) => {
              console.log("access")
              originalRequest.headers["Authorization"] =
                "Bearer:" + accessToken;
              console.log("access: " + accessToken);
              return axiosInstance(originalRequest);
            })
            .catch((err) => {
              console.log("err");
              return Promise.reject(err);
            });
        }
        console.log("no refreshing"); 
        originalRequest._retry = true;
        console.log(originalRequest._retry);
        isRefreshing = true;
        return new Promise((resolve, reject) => { 
          postMethod("auth/token",null,null).then((result) => {
            console.log("result:",result)

              setToken(result.data.access_token);
              
              axiosInstance.defaults.headers.common["Authorization"] =
                "Bearer:" + result.data.access_token;
              originalRequest.headers["Authorization"] =
                "Bearer:" + result.data.access_token;

              processQueue(null, result.data.access_token);
              resolve(axiosInstance(originalRequest));
            })
            .catch((err) => {

              console.log(err.response)
              processQueue(err, null);
              reject(err);
            })
            .then(() => {
              isRefreshing = false;
            });
          //TODO:Eğer refresh tokenın da süresi dolmuşsa burda history.push oluyor. ama diğer tarafı bozuyor
        });
      } 
      return Promise.reject(error);
  }
);

它卡在某个地方了。我使用console.log来调试它。从控制台;

发布http://localhost:5000/api/auth/token?null 401(未经授权)

之后什么都没发生。我该怎么办?谢谢你的帮助

共有1个答案

沃宇
2023-03-14
const axiosInstance = axios.create({
     baseURL: baseURL,
     timeout: 5000,
     headers: {
                'Authorization': localStorage.getItem('access_token') ? "JWT " + localStorage.getItem('access_token') : null,
                'Content-Type': 'application/json',
                'accept': 'application/json'
     }
});

axiosInstance.interceptors.response.use(
    response => response,
    error => {
        const originalRequest = error.config;

        // Prevent infinite loops
        if (error.response.status === 401 && originalRequest.url === baseURL+'token/refresh/') {
            window.location.href = '/login/';
            return Promise.reject(error);
        }

        if (error.response.data.code === "token_not_valid" &&
            error.response.status === 401 && 
            error.response.statusText === "Unauthorized") 
            {
                const refreshToken = localStorage.getItem('refresh_token');

                if (refreshToken){
                    const tokenParts = JSON.parse(atob(refreshToken.split('.')[1]));

                    // exp date in token is expressed in seconds, while now() returns milliseconds:
                    const now = Math.ceil(Date.now() / 1000);
                    console.log(tokenParts.exp);

                    if (tokenParts.exp > now) {
                        return axiosInstance
                        .post('/token/refresh/', {refresh: refreshToken})
                        .then((response) => {
            
                            localStorage.setItem('access_token', response.data.access);
                            localStorage.setItem('refresh_token', response.data.refresh);
            
                            axiosInstance.defaults.headers['Authorization'] = "JWT " + response.data.access;
                            originalRequest.headers['Authorization'] = "JWT " + response.data.access;
            
                            return axiosInstance(originalRequest);
                        })
                        .catch(err => {
                            console.log(err)
                        });
                    }else{
                        console.log("Refresh token is expired", tokenParts.exp, now);
                        window.location.href = '/login/';
                    }
                }else{
                    console.log("Refresh token not available.")
                    window.location.href = '/login/';
                }
        }
      
     
      // specific error handling done elsewhere
      return Promise.reject(error);
  }
);
 类似资料:
  • 我需要(在拦截器类中)对403禁止的HTTP状态(获取/刷新)JWT令牌作出反应,并使用新令牌重试请求。 在下面的代码中,当服务器返回错误响应时,它将转到成功回调(而不是像我预期的那样进入错误回调),事件是typeof object(这在错误响应的反应中是无用的)。事件对象如下所示:{type:0}。 问题: -当我需要刷新accessToken并重试http请求时,如何在HttpIntercep

  • 我有一个OkHttp拦截器,当请求得到401 HTTP错误时,它应该请求一个令牌。现在,登录服务的请求完成了,但随后链路中断,原始请求不再重试。下面是我的拦截器的拦截方法: reLogin()方法是: 新:正如Mitesh Machhoya所说,我尝试了两个不同的改型实例,一个带有拦截器的okhttp客户端,另一个没有。现在登录调用没有被拦截,但是拦截器的执行被中断了,我的意思是这个类的日志跟踪是

  • 我有 401 拦截器,当access_token过期时,有一个请求的成功案例。拦截器重新加载令牌并返回 next.handle(customReq)。但是当同时发出 2 个或更多请求并且两个请求的令牌都已过期时,我遇到了问题,因为第二个请求尝试再次刷新,但现在刷新令牌无效。所以。。。。我尝试设置一个标志只执行一次,并使用自定义可观察量返回。问题是组件现在永远不会成功,我无法删除加载器。 HTTP

  • 问题内容: 我有一个有角度的应用程序,有时每个状态会执行多个$ http.get请求。该应用将JWT用于带有刷新令牌的用户身份验证。API服务器会发送由于身份验证错误而失败的每个请求。我做了一个请求,该请求在401错误时请求带有刷新令牌的新令牌,然后重新发送原始请求。 问题是,如果一个状态发出例如2个$ http.get请求,并且都获得401响应,那么我将访问令牌更新两次。显然,我只想刷新一次令牌

  • 我有一个Spring 3 Web应用程序,它实现了两个拦截器。我正在使用一个带有@Configuration注释的配置类。代码如下: 无论我将拦截器添加到注册表的顺序是什么,allIntericetor的preHandle函数总是在home Intericetor的preHandle之前调用。有人知道如何控制拦截器调用的顺序吗? 谢谢

  • 我试图在javascript中为fetch创建一个拦截器(更具体地说是React)。它应该从每次调用的fetch中获取结果,如果是401错误,它应该向另一个路由发起新的fetch调用,以获取cookie(刷新令牌)。然后,应该再次尝试原始的fetch调用(因为现在用户已经登录)。 我已经成功地触发了新的fetch调用,并为每个调用发回了cookie,但我遇到了以下两个问题: 我似乎在使用async