我有一个使用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?null401(未经授权(
不刷新//它是第三个if语句之后的第一行
岗位http://localhost:5000/api/auth/token?null401(未经授权(
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 => {});
});
};
希望能有所帮助!