【发布时间】:2019-01-09 19:49:18
【问题描述】:
我们最近在this question 中讨论了用于 OAuth 身份验证令牌刷新的 axios 拦截器。
拦截器应该做的是拦截任何带有401状态码的响应并尝试刷新令牌。
考虑到这一点,接下来要做的是从拦截器返回一个 Promise,这样任何通常会失败的请求都会在令牌刷新后运行,因为没有任何反应。
主要问题是,拦截器只检查401 状态码,这还不够,因为refreshToken 在失败时也会返回401 状态码——而且我们有一个循环。
我想到了两种可能的情况:
- 检查调用的 URL,如果是
/auth/refresh,则不应尝试刷新令牌; - 在调用
refreshToken逻辑时省略拦截器
第一个选项在我看来有点“不动态”。第二个选项看起来很有希望,但我不确定它是否可能。
那么主要的问题是,我们如何区分/识别拦截器中的调用并为它们运行不同的逻辑而无需专门“硬编码”它,或者有什么方法可以省略指定调用的拦截器?提前谢谢你。
拦截器的代码可能有助于理解问题:
Axios.interceptors.response.use(response => response, error => {
const status = error.response ? error.response.status : null
if (status === 401) {
// will loop if refreshToken returns 401
return refreshToken(store).then(_ => {
error.config.headers['Authorization'] = 'Bearer ' + store.state.auth.token;
error.config.baseURL = undefined;
return Axios.request(error.config);
})
// Would be nice to catch an error here, which would work if the interceptor is omitted
.catch(err => err);
}
return Promise.reject(error);
});
和令牌刷新部分:
function refreshToken(store) {
if (store.state.auth.isRefreshing) {
return store.state.auth.refreshingCall;
}
store.commit('auth/setRefreshingState', true);
const refreshingCall = Axios.get('get token').then(({ data: { token } }) => {
store.commit('auth/setToken', token)
store.commit('auth/setRefreshingState', false);
store.commit('auth/setRefreshingCall', undefined);
return Promise.resolve(true);
});
store.commit('auth/setRefreshingCall', refreshingCall);
return refreshingCall;
}
【问题讨论】:
标签: oauth-2.0 oauth axios interceptor