gpt4 book ai didi

oauth-2.0 - 通过 axios 中的拦截器自动刷新访问 token

转载 作者:搜寻专家 更新时间:2023-10-30 22:09:42 24 4
gpt4 key购买 nike

我们最近在 this question 中讨论了用于 OAuth 身份验证 token 刷新的 axios 拦截器| .

拦截器应该做的是拦截任何带有 401 状态码的响应并尝试刷新 token 。考虑到这一点,接下来要做的是从拦截器返回一个 Promise,这样任何通常会失败的请求都会在 token 刷新后正常运行。

主要问题是,拦截器只检查 401 状态码,这还不够,因为 refreshToken 也会返回 401 失败时的状态代码 - 我们有一个循环。

我想到了两种可能的情况:

  1. 检查调用的 URL,如果是 /auth/refresh,则不应尝试刷新 token ;
  2. 在调用 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);
});

和token刷新部分:

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

最佳答案

我可能找到了一种更简单的方法来处理这个问题:使用 axios.interceptors.response.eject()在我调用/api/refresh_token 端点时禁用拦截器,并在之后重新启用它。

代码:

/**
* Wrap the interceptor in a function, so that i can be re-instantiated
*/
function createAxiosResponseInterceptor() {
const interceptor = axios.interceptors.response.use(
(response) => response,
(error) => {
// Reject promise if usual 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.
*
* Must be re-attached later on or the token refresh will only happen once
*/
axios.interceptors.response.eject(interceptor);

return axios
.post("/api/refresh_token", {
refresh_token: this._getToken("refresh_token"),
})
.then((response) => {

saveToken();
error.response.config.headers["Authorization"] =
"Bearer " + response.data.access_token;
// Retry the initial call, but with the updated token in the headers.
// Resolves the promise if successful
return axios(error.response.config);
})
.catch((error2) => {
// Retry failed, clean up and reject the promise
destroyToken();
this.router.push("/login");
return Promise.reject(error2);
})
.finally(createAxiosResponseInterceptor); // Re-attach the interceptor by running the method
}
);
}
createAxiosResponseInterceptor(); // Execute the method once during start

以上代码将:

  • 拦截以 https 状态代码 401 返回的调用
  • 弹出拦截器,防止死循环
  • 获取新 token
  • 通过用新 token 替换旧 token 来复制和修改初始请求
  • 使用 header 中的新 token 重试初始请求
  • 在重试请求后重新附加拦截器,无论结果如何。

关于oauth-2.0 - 通过 axios 中的拦截器自动刷新访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51646853/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com