用于令牌刷新的 axios 全局拦截器
Posted
技术标签:
【中文标题】用于令牌刷新的 axios 全局拦截器【英文标题】:Axios global interceptor for token refresh 【发布时间】:2020-03-04 05:34:06 【问题描述】:好的,这是我遇到这个问题的第三面墙,首先这是我的 axios 配置文件
import axios from "axios";
import withRouter from "react-router-dom";
const instance = axios.create(
baseURL: process.env.REACT_APP_API,
headers:
"content-type": "application/json"
,
responseType: "json"
);
function pushToLogin()
this.props.history.push("/");
function createAxiosResponseInterceptor(axiosInstance)
const interceptor = axiosInstance.interceptors.response.use(
response => response,
error =>
// Reject promise if usual error
console.log(error);
if (error.response.status !== 401)
return Promise.reject(error);
/*
* When response code is 401, try to refresh the token.
* Eject the interceptor so it doesn't loop in case
* token refresh causes the 401 response
*/
axiosInstance.interceptors.response.eject(interceptor);
return axiosInstance
.post("token/refresh/",
refresh: localStorage.getItem("refreshToken")
)
.then(response =>
localStorage.setItem("accessToken", response.data.access);
error.response.config.headers["Authorization"] =
"Bearer " + response.data.access;
return axiosInstance(error.response.config);
)
.catch(error =>
localStorage.setItem("accessToken", null);
localStorage.setItem("refreshToken", null);
pushToLogin();
return Promise.reject(error);
)
.finally(createAxiosResponseInterceptor(this));
);
createAxiosResponseInterceptor(instance);
export default withRouter(instance);
我想要的是: 请求得到 401 > 获取一个新的令牌并存储它 > 重复请求 > 如果它很好去我们很好,如果没有返回它是正常的错误。
发生了什么:请求得到 401 > 获取新令牌并存储它 > 重复请求> 如果它很好,我们很高兴,如果不是,它进入我的拦截器上的最后一个 catch 块,我认为这是专门针对的对于 refreshToken 请求,或者至少这就是我想要的。
额外问题:如您所见,我想在 refreshToken 失败时推送登录,我正在尝试使用 withRouter 但我在那条推送线上cannot read props of undefined
,所以这是另一个问题。
非常感谢!
编辑:即使这个请求是通过其他方式完成的,我也想知道我的代码出了什么问题,而不是了解别人的代码。
【问题讨论】:
我创建了 axios-middleware 模块来隔离拦截器的行为并做了一些示例,其中一个正是您要问的:emileber.github.io/axios-middleware/#/examples/auth-middleware Axios Interceptors retry original request and access original promise的可能重复 @EmileBergeron 即使这是一个类似的最终目标,我也宁愿找出我自己的实现存在错误的问题,而不是学习别人的。 我的意思是你可以使用这个例子来实现你自己的拦截器。 【参考方案1】:我切换到使用axios-auth-refresh 包,我正在使用的配置代码在这里:
import axios from "axios";
import createAuthRefreshInterceptor from "axios-auth-refresh";
const instance = axios.create(
baseURL: process.env.REACT_APP_API,
headers:
"content-type": "application/json"
,
responseType: "json"
);
const refreshAuthLogic = failedRequest =>
instance
.post("token/refresh/",
refresh: localStorage.getItem("refreshToken")
)
.then(tokenRefreshResponse =>
localStorage.setItem("accessToken", tokenRefreshResponse.data.access);
failedRequest.response.config.headers["Authorization"] =
"Bearer " + tokenRefreshResponse.data.access;
return Promise.resolve();
)
.catch(error =>
console.log("refresh fail");
localStorage.setItem("accessToken", null);
localStorage.setItem("refreshToken", null);
//pushToLogin();
return Promise.reject(error);
);
createAuthRefreshInterceptor(instance, refreshAuthLogic);
export default instance;
【讨论】:
以上是关于用于令牌刷新的 axios 全局拦截器的主要内容,如果未能解决你的问题,请参考以下文章