如何静默刷新认证Token并重发HttpRequest请求
Angular 4+ 拦截器401重试:Token刷新后重发请求
解决你的两个核心问题
1. 为什么示例不用subscribe就能触发请求?
Angular的HttpClient在发起请求时,会自动订阅你从intercept方法返回的Observable。你在refreshToken()里手动调用subscribe(),虽然能触发Token刷新请求,但会打破拦截器的链式流——返回的Observable已经被提前订阅,拦截器无法利用这个流完成后续的请求重发操作。
2. 用什么操作器重发请求?
用switchMap操作符最合适:它会等待Token刷新的Observable完成,然后切换到重发请求的Observable。tap仅用于执行副作用(比如打印日志),不会改变流的内容;mergeMap也能实现,但switchMap可以避免同时触发多个Token刷新请求(如果有多个401请求同时进来,只会保留最后一个刷新操作)。
修正后的完整代码
1. 改造AuthenticationService的refreshToken方法
去掉手动subscribe,把存Cookie的逻辑放到tap里,保持流的链式传递:
refreshToken(): Observable<KeyCloakToken> { return this.http.post<KeyCloakToken>(`${this.authUrl}/auth/refresh`, { refreshToken: this.refreshToken }) .pipe( tap(data => { console.log("tap in refreshToken", data); this.saveCookie(data); // 存Cookie的逻辑放到tap中,无需手动订阅 }) ); }
2. 完善AuthInterceptor的拦截逻辑
在catchError中连接Token刷新流和请求重发流,同时处理刷新失败的情况:
@Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private auth: AuthenticationService) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { // 先添加初始认证头 let authRequest = this.addAuthHeader(request); return next.handle(authRequest).pipe( catchError((error: any) => { // 仅处理401的HTTP错误 if (error instanceof HttpErrorResponse && error.status === 401) { // 刷新Token后重发请求 return this.auth.refreshToken().pipe( switchMap(() => { // Token刷新完成后,重新构建带新Token的请求 const newAuthRequest = this.addAuthHeader(request); // 重发原请求 return next.handle(newAuthRequest); }), // 处理Token刷新失败的情况(比如跳转到登录页) catchError(refreshError => { console.error("Token刷新失败", refreshError); // 这里可以添加跳转到登录页的逻辑,比如:this.router.navigate(['/login']) return throwError(() => refreshError); }) ); } // 非401错误,直接抛出原错误 return throwError(() => error); }) ); } // 封装添加认证头的方法 private addAuthHeader(request: HttpRequest<unknown>): HttpRequest<unknown> { const token = this.auth.getToken(); // 假设你有获取最新Token的方法 if (token) { return request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return request; } }
内容的提问来源于stack exchange,提问作者tung
相关产品推荐
相关产品推荐

