Angular 6 HTTP拦截器刷新令牌401处理 [英] Angular 6 HTTP Interceptor Refresh token 401 handling
问题描述
我已经构建了我的AuthInterceptor,它在出现401错误时发送了获取新令牌的请求.
I have built my AuthInterceptor which on a 401 error sends a request to get a new token.
当我遇到401错误时会调用handle401Error方法,但是我的this.authService.refreshToken().pipe()似乎没有任何响应
The handle401Error method is called when I encounter a 401 error, But I don't seem to be getting any response in my this.authService.refreshToken().pipe()
AuthInterceptor
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))
)
}
}
}
AuthService刷新令牌
refreshToken(): Observable<string> {
console.log('refreshToken');
let token = 'xxx-xxx-xx';
return of(token).pipe(delay(1000));
}
推荐答案
除了案例401"中缺少的收益外,这就是我的处理方式.
Besides the missing return in 'case 401', here's how I would handle it.
基本思想是,您希望在收到新的刷新令牌后重试整个可观察的对象.另外,该请求被修补在一个可观察的内部,以便每次重试时都会从auth服务获取新令牌.
The basic idea is that you want to retry the entire observable once you receive the new refresh token. Also, the request is patched inside an observable so that on each retry it will get the new token from the auth service.
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;
})
)
)
);
}
}
这篇关于Angular 6 HTTP拦截器刷新令牌401处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!