我有一个jwt / refresh令牌授权。
当/api/auth/token/refresh
由于刷新令牌不存在/过期而导致BadRequest失败时,我试图通过catchError
捕获错误,而不是在控制台日志中抛出错误做next.handle(request)
以消除错误。当前,只要catchError出现,它就会无限循环运行。换句话说,发现错误后,我要logout()
个用户,该用户自己执行一个HTTP发布请求,然后导航到登录页面。
我之所以return this.authService.logout()
是因为我在logout()
中有一个HTTP发布请求,如果我不以某种方式订阅,它将无法执行。
auth.interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private router: Router,
private authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
catchError((error: HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
return this.handleHttpResponseError(request, next);
}
}
return throwError(error);
})
);
}
private handleHttpResponseError(request: HttpRequest<any>, next: HttpHandler) {
const accessToken = this.authService.getJwtToken();
// if jwt token is not set, we just let the request execute
if (!accessToken) {
return next.handle(request);
}
// if jwt token has not expired yet, we add the authorize header
// otherwise we refresh the token
if (!this.authService.isTokenExpired()) {
// add "Authorization: Bearer token" to the current request's headers
return next.handle(this.attachTokenToRequest(request, accessToken));
} else {
// when the JWT token expires
return this.authService.refreshToken()
.pipe(
switchMap(token => {
console.log('Token refreshed.');
return next.handle(this.attachTokenToRequest(request, token));
}),
catchError(error => {
console.log('INFINITE LOOP HERE.');
return this.authService.logout()
.pipe(
switchMap(error2 => {
console.log(error2);
this.router.navigate['/log-in'];
return next.handle(request);
})
);
})
);
}
}
private attachTokenToRequest(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
}
}
// auth.service.ts
logout() {
return this.httpClient.post<AccessToken>(`${this.actionUrl}/token/revoke`, { 'refreshToken': this.getRefreshToken() })
.pipe(
map(() => {
console.log('revoked token');
localStorage.removeItem(this.JWT_TOKEN);
localStorage.removeItem(this.REFRESH_TOKEN);
return true;
})
);
}
答案 0 :(得分:0)
我面对了这个问题,最终发现这是由于路由规则所致!
发生问题是因为我在app-routing.module.ts中设置了onSameUrlNavigation: 'reload'
,所以一旦我从HttpErrorInterceptor类将页面重定向到登录页面,拦截器就会陷入无限循环。
因此,我们有两种选择来防止发生此无限循环:
删除onSameUrlNavigation: 'reload'
或
通过检查是否已经是登录页面来防止发生多次重定向:
因此,在http-error.interceptor.ts文件中,您可以导入Router
并使用以下条件:
if(this.router.url != '/login')
this.router.navigate(["login"]);
它对我有用,希望它能对其他人有所帮助。