所以我对 axios 和上下文相当陌生,但我有一个在应用程序级别提供的身份验证上下文,并且该上下文由多个子组件使用。在这种情况下,我有一个 axios 拦截器,它检查 401(未经授权(的请求,然后调用刷新令牌 api 并用新令牌替换令牌。我唯一担心的是第二次调用刷新令牌 API 时,它会进入调用刷新令牌 API 的无限循环?知道我做错了什么吗?任何帮助将不胜感激。
身份验证上下文.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);
});
我已经做了类似的事情来在令牌过期时获取刷新令牌,并且遇到了同样的问题,实际上,您正在使用相同的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;
}
希望上面的例子能帮到你
嘿,我知道这是一个老问题,但似乎您的问题是使用相同的 axios 实例来请求刷新令牌,本质上是一个嵌套的刷新令牌循环。您可以做的是创建一个新的 axios 实例(与初始实例一起,您将同时使用它们(,而无需像这样拦截器:const noInterceptAxios = axios.create();
,然后使用它发送不需要检查访问令牌的请求,return noInterceptAxios.post(`/Identity/Refresh).then().catch()
.
@J.Naude 我做过类似的事情,但我为我的一个项目编写了一个围绕 axios 的通用包装器,它处理几乎所有边缘情况
https://gist.github.com/tapandave/01960228516dd852a49c74d16c0fddb1