Angular 6 HTTP 拦截器刷新令牌 401 处理



我已经构建了我的AuthInterceptor,它在401错误上发送请求以获取新令牌。

当我遇到 401 错误时调用 handle401Error 方法,但我似乎在我的 this.authService.refreshToken((.pipe(( 中没有得到任何响应

身份验证拦截器

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap, switchMap } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
isRefreshingToken:boolean = false;
constructor(public authService: AuthService, private injector: Injector) {}
addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
return req.clone({ setHeaders: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
}})
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = this.addToken(request, this.authService.getToken())
return next.handle(request).pipe (
catchError((error: Error) => {
if(error instanceof HttpErrorResponse){
console.log('err', error);
switch(error.status) {
case 401:
this.handle401Error(request, next)
default:
return throwError(error);
}
} else {
return throwError(error);
}
})
);
}
handle401Error(request: HttpRequest<any>, next: HttpHandler){
console.log('handle 401');
if(!this.isRefreshingToken) { //do not send another refresh token request if already in progress
this.isRefreshingToken = true;
return this.authService.refreshToken().pipe(
switchMap((newToken: string) => {
console.log('newToken', newToken) // I DO NOT GET A VALUE HERE
if (newToken) { 
return next.handle(this.addToken(request, newToken));
}
}),
catchError((error) => {
console.log('error', error) //NOR DO I GET AN ERROR
return throwError(error)
}),
tap(data => console.log(data))
)
}
}
}

身份验证服务刷新令牌

refreshToken(): Observable<string> {
console.log('refreshToken');
let token = 'xxx-xxx-xx';
return of(token).pipe(delay(1000));
}

除了"案例 401"中缺少的返回之外,以下是我将如何处理它。

基本思想是,您希望在收到新的刷新令牌后重试整个可观察量。此外,请求在可观察量中修补,以便在每次重试时,它将从身份验证服务获取新令牌。

import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { catchError, retryWhen, switchMap, tap } from 'rxjs/operators';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private retryRequest = Symbol('reload');
private refreshToken = this.authService.refreshToken()
.pipe(
tap(newToken => {
if (newToken) {
throw this.retryRequest;
}
}),
share(),
) as Observable<any>;
constructor(public authService: AuthService) { }
private addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
return req.clone({
setHeaders: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const request$ = new Observable<HttpRequest<any>>(observer => {
observer.next(this.addToken(request, this.authService.getToken()));
observer.complete();
});
return request$.pipe(
switchMap(req => next.handle(req)),
catchError((error: Error) => {
if (error instanceof HttpErrorResponse) {
switch (error.status) {
case 401:
return this.refreshToken;
default:
throw error;
}
} else {
throw error;
}
}),
retryWhen(err$ =>
err$.pipe(
tap(err => {
if (err === this.retryRequest) { return; }
throw err;
})
)
)
);
}
}

最新更新