Angular拦截器:捕获错误后重新执行原HTTP请求
Angular拦截器:401认证失败后重新执行请求的解决方案
要实现401重新认证后自动重试原请求,核心是利用RxJS操作符在刷新token完成后重新发起请求,同时要避免无限循环问题。以下是修改后的完整实现:
import { HttpContextToken, type HttpRequest, type HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http'; import { inject } from '@angular/core'; import { AuthService } from './auth.service'; import { catchError, switchMap, throwError } from 'rxjs'; export const REFRESHER_TOKEN_INTERCEPTOR = new HttpContextToken(() => false); export const authInterceptor: HttpInterceptorFn = (req: HttpRequest<any>, next) => { const authService = inject(AuthService); const operationName = req.body?.operationName?.toLowerCase() || ''; const isRefresherToken = operationName === 'refreshtoken'; // 获取对应token:刷新请求用refresh token,其他用JWT token const jwtToken = authService.getToken(isRefresherToken); if (jwtToken) { const clonedReq = req.clone({ setHeaders: { Authorization: `Bearer ${jwtToken}` } }); return next(clonedReq).pipe( catchError((err: any) => { // 仅处理HTTP 401错误,且当前请求不是刷新token的请求(避免循环) if (err instanceof HttpErrorResponse && err.status === 401 && !isRefresherToken) { // 调用刷新token方法,注意refreshToken需返回Observable return authService.refreshToken().pipe( switchMap(() => { // 刷新成功后,获取最新的JWT token,克隆原请求并更新头信息 const newJwtToken = authService.getToken(false); const newClonedReq = req.clone({ setHeaders: { Authorization: `Bearer ${newJwtToken}` } }); // 重新发起原请求 return next(newClonedReq); }), // 如果刷新token也失败,直接抛出错误 catchError(refreshErr => throwError(() => refreshErr)) ); } // 其他错误直接抛出 return throwError(() => err); }) ); } return next(req); };
关键说明
- 避免无限循环:判断当前请求是否是
refreshtoken操作,防止刷新token失败后再次进入拦截器触发刷新逻辑。 - RxJS操作符使用:用
switchMap在刷新token的Observable完成后,切换到重新发起的原请求Observable。 - 更新请求头:刷新token后必须重新获取最新的JWT token,克隆原请求并替换Authorization头,确保使用有效凭证发起重试。
- 错误传递:如果刷新token操作本身失败,直接抛出错误,避免静默吞掉问题。
内容的提问来源于stack exchange,提问作者DanyBoy
相关产品推荐
相关产品推荐

