【发布时间】:2018-06-14 12:17:41
【问题描述】:
我的 axios 响应中有以下拦截器:
window.axios.interceptors.response.use(
response => {
return response;
},
error => {
let errorResponse = error.response;
if (errorResponse.status === 401 && errorResponse.config && !errorResponse.config.__isRetryRequest) {
return this._getAuthToken()
.then(response => {
this.setToken(response.data.access_token, response.data.refresh_token);
errorResponse.config.__isRetryRequest = true;
errorResponse.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
return window.axios(errorResponse.config);
}).catch(error => {
return Promise.reject(error);
});
}
return Promise.reject(error);
}
);
_getAuthToken 方法是:
_getAuthToken() {
if (!this.authTokenRequest) {
this.authTokenRequest = window.axios.post('/api/refresh_token', {
'refresh_token': localStorage.getItem('refresh_token')
});
this.authTokenRequest.then(response => {
this.authTokenRequest = null;
}).catch(error => {
this.authTokenRequest = null;
});
}
return this.authTokenRequest;
}
代码深受https://github.com/axios/axios/issues/266#issuecomment-335420598 的启发。
总结:当用户调用 API 并且他的 access_token 已过期(API 返回 401 代码)时,应用程序调用 /api/refresh_token 端点以获取新的 access_token。如果在进行此调用时 refresh_token 仍然有效,则一切正常:我得到一个新的 access_token 和一个新的 refresh_token,并且用户请求的初始 API 调用再次进行并正确返回。
当 refresh_token 也过期时会出现问题。
在这种情况下,对 /api/refresh_token 的调用返回 401 并且没有任何反应。我尝试了几件事,但无法将用户重定向到应用程序的登录页面。
我发现在这种情况下,_getAuthToken 方法中的 if (!this.authTokenRequest) 语句会返回一个从未解决的未决 Promise。我不明白为什么这是一个承诺。在我看来它应该是空的......
我是 Promises 的新手,所以我可能会遗漏一些东西! 感谢您的帮助!
编辑:
我可能找到了一种更简单的方法来处理这个问题:当我调用 /api/refresh_token 端点时,使用 axios.interceptors.response.eject() 禁用拦截器,然后重新启用它。
代码:
createAxiosResponseInterceptor() {
this.axiosResponseInterceptor = window.axios.interceptors.response.use(
response => {
return response;
},
error => {
let errorResponse = error.response;
if (errorResponse.status === 401) {
window.axios.interceptors.response.eject(this.axiosResponseInterceptor);
return window.axios.post('/api/refresh_token', {
'refresh_token': this._getToken('refresh_token')
}).then(response => {
this.setToken(response.data.access_token, response.data.refresh_token);
errorResponse.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
this.createAxiosResponseInterceptor();
return window.axios(errorResponse.config);
}).catch(error => {
this.destroyToken();
this.createAxiosResponseInterceptor();
this.router.push('/login');
return Promise.reject(error);
});
}
return Promise.reject(error);
}
);
},
它看起来好还是坏?任何建议或评论表示赞赏。
【问题讨论】:
标签: laravel vue.js es6-promise axios laravel-passport