【发布时间】:2018-07-21 03:21:23
【问题描述】:
我在 Angular5 中使用拦截器为每个请求添加一个 Authorization 标头。但是,来自后端的令牌可能会过期,在这种情况下,必须进行令牌刷新。如果多个HttpRequest<any>同时进来,我没办法让它们排队,所以会发出多个未经授权的请求,服务器会返回多个401响应,直到最后一个令牌刷新完成,剩余的请求可以重试。目前,每个请求大约需要 3 次失败尝试,直到其中一个最终成功。当前实现:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private refreshInProgress: boolean = false;
constructor(private injector: Injector, private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `${this.injector.get(AuthService).getAccessToken()}`
}
});
return next.handle(request).catch((error: any) => {
if(error instanceof HttpErrorResponse) {
switch(error.status) {
case 401:
if(!this.refreshInProgress) {
this.refreshInProgress = true;
this.injector.get(AuthService).getRefreshToken().subscribe(
(success: boolean) => {
if(!success) {
this.router.navigate(['/signin']);
}
}
);
return this.intercept(request, next);
} else {
return this.intercept(request, next).delay(700);
}
default:
return Observable.throw(error);
}
}
return Observable.throw(error);
})
.finally(() => {
this.refreshInProgress = false;
});
}
}
如您所见,我所知道的唯一选择是添加 refreshInProgress 布尔值以尝试阻止其他请求立即发出,而是尝试让它们等待 700 毫秒后再重试。这不是一个很好的解决方案,但它可以通过。
我想我想做的是创建一个unauthorizedRequestQueue 或者一个BehaviorSubject<HttpRequest<any>>,然后如果一个401 已经出去,让后续的HttpRequests 排队,直到第一个调用返回刷新令牌。但是,我对 RxJs 库仍然很陌生,并且无法弄清楚如何做这样的事情。
我希望 SO 社区能够将我推向正确的方向,让我了解如何实现此类功能。或者也许还有其他更好的方法来做我想做的事情?
【问题讨论】:
标签: angular rxjs observable interceptor subject