[英]Angular HTTP Interceptor wait http requests until get a refresh token
我已經構建了我的 AuthInterceptor,它在 401 錯誤時發送請求以獲取新令牌。
當我遇到 401 錯誤時會調用 handle401Error 方法,但我正在嘗試等待其他 HTTP 請求,直到我獲得新令牌。 但是它不會等到獲得新的刷新令牌,盡管它正在對一個新的訪問令牌進行 HTTP 調用。 請找到我附上的截圖。
攔截器
isRefreshingToken = false;
tokenSubject: BehaviorSubject<string | null> = new BehaviorSubject<string | null>(null);
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const timeOut = appSettings.ajaxTimeout;
const retryCount = appSettings.retryCount;
const retryDelay = appSettings.retryDelayMS;
return next.handle(request).pipe(
timeout(timeOut),
catchError((error) => {
if (error instanceof HttpErrorResponse) {
const httpErrorCode: number = error['status'];
switch (httpErrorCode) {
case StatusCodes.BAD_REQUEST:
return throwError(error);
//return this.handle400Error(error);
case StatusCodes.UNAUTHORIZED:
return this.handle401Error(request, next);
default:
this._toastr.error(
'Sorry! something went wrong.',
'Error!'
);
return throwError(error);
}
} else {
return throwError(error);
}
}),
retryWhen((errors) => {
return errors.pipe(
concatMap((error, count) => {
if (count < retryCount) {
return of(error);
}
return throwError(error);
}),
delay(retryDelay)
);
})
);
}
handle401Error(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
console.log('401');
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
return this._spotify.getRefreshToken().pipe(
switchMap((authData: ISpotifyTokens) => {
if (authData) {
console.log('new token success');
this.updateTokenInCookie(authData);
this.tokenSubject.next(authData.access_token);
return next.handle(request);
}
return this.logoutUser();
}),
catchError((error) => {
// If there is an exception calling 'refreshToken', bad news so logout.
return this.logoutUser();
}),
finalize(() => {
this.isRefreshingToken = false;
})
);
} else {
return next.handle(request);
}
}
updateTokenInCookie(authData: ISpotifyTokens) {
this._spotify.updateTokensInStorage(authData);
this._spotify.startRefreshTokenTimer(authData.expires_in);
}
logoutUser() {
this._spotify.clearTokensFromStorage();
this._router.navigate(['/welcome']);
return throwError('');
}
我已經使用下面的代碼解決了這個問題。 如果有人有任何黃油解決方案,請提出建議。
private isRefreshingToken = false;
private timeOut = appSettings.ajaxTimeout;
private tokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
timeout(this.timeOut),
catchError((error) => {
if (error instanceof HttpErrorResponse) {
const httpErrorCode: number = error['status'];
switch (httpErrorCode) {
case StatusCodes.BAD_REQUEST:
return throwError(error);
case StatusCodes.UNAUTHORIZED:
return this.handle401Error(request, next);
default:
this._toastr.error(
'Sorry! something went wrong.',
'Error!'
);
return throwError(error);
}
} else {
return throwError(error);
}
})
);
}
private handle401Error(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
return this._spotify.getRefreshToken().pipe(
switchMap((response: ISpotifyTokens) => {
console.log('updating on 401');
// Updating new token in cookie
this._spotify.updateTokensInStorage(response, false);
this.tokenSubject.next(response.access_token);
return next.handle(
this.addTokenInHeader(request, response.access_token)
);
}),
catchError((error) => {
// If there is an exception calling 'refreshToken', bad news so logout.
this.logoutUser();
return throwError('');
}),
finalize(() => {
this.isRefreshingToken = false;
})
);
} else {
return this.tokenSubject.pipe(
filter((token) => token != null),
take(1),
switchMap((token) => {
return next.handle(this.addTokenInHeader(request, token));
})
);
}
}
addTokenInHeader(
request: HttpRequest<any>,
token: string
): HttpRequest<any> {
return request.clone({
setHeaders: { Authorization: 'Bearer ' + token }
});
}
logoutUser(): void {
this._spotify.clearTokensFromStorage();
this._router.navigate(['/welcome']);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.