繁体   English   中英

为刷新令牌反应 axios 拦截器

[英]React axios interceptor for refresh token

我有一个使用 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 来调试它。 从控制台;

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

不刷新 // 它是第三个 if 语句之后的第一行

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

isRefreshing // 它来自第三个 if 语句

isRefreshing2 // 它来自第三个 if 语句

在那之后什么也没有发生。 我该怎么办 ? 谢谢你的帮助

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);
  }
);

按照我下面的代码

const axios = require('axios');
import store from '../redux/store';
import AsyncStorage from '@react-native-async-storage/async-storage';
// create your axis here
const axiosService = axios.create({
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
    Authorization: `Bearer ${yourTokenHere}`,
  },
});

axiosService.interceptors.response.use(
  response => {
    return response;
  },
  async error => {
    // unauthen error 401
    let originalConfig = error.config;
    if (error.response.status === 401) {
      // get token from storage
      const token = await AsyncStorage.getItem('token');
      if (token) {
        // call function hanldeRefresh
        const respRefresh = await handleRefresh(token);
        if (respRefresh && respRefresh.status === 200) {
          const filterToken =
            respRefresh.headers.authorization.split('Bearer ')[1];
          // save new refresh token to storage
          AsyncStorage.setItem('token', filterToken);
          // reset header for originalConfig with new token here
          originalConfig = {
            ...originalConfig,
            headers: {
              ...originalConfig.headers,
              Authorization: `Bearer ${filterToken}`,
            },
          };
          // dispatch action save new token to state for redux saga
          store.dispatch({
            type: 'REFRESH_TOKEN_SAGA',
            payload: filterToken && filterToken,
          });
        }
      }
      // continue send currently request
      return axiosService(originalConfig);
    }
    return Promise.reject(error.response.data);
  },
);

// function handle refresh token

// create new axios to avoid loop error 401 for axios response if refresh token die

const axiosServiceRefresh = axios.create({
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
  },
});
const handleRefresh = async token => {
  // set header for axios refresh
  axiosServiceRefresh.defaults.headers.common.Authorization = `Bearer ${token}`;
  return new Promise((resolve, reject) => {
    axiosServiceRefresh
      .post(yourRefreshTokenPath, param)
      .then(response => {
        resolve(response);
      })
      .catch(error => {});
  });
};

希望能帮上忙!

暂无
暂无

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

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