首页 > 解决方案 > 在拦截器中收到 403 后无法重发请求

问题描述

我试图拦截导致 403 的请求(因为令牌过期),然后执行请求以获取新令牌,以便能够再次执行失败的请求。

但是由于某种原因,带有新令牌的 next.handle(request) 没有执行被拦截的请求。

@Injectable()
export class AuthExpiredInterceptor implements HttpInterceptor {
  constructor(
    private accountService: AccountService,
    private readonly authService: AuthService,
    private readonly router: Router
  ) {}

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      catchError((error) => {
        if (error instanceof HttpErrorResponse && error.status === 403) {
          this._handle403Error(request, next);
        }
        return throwError(error);
      })
    );
  }

  _handle403Error(request: HttpRequest<any>, next: HttpHandler) {
    const refreshToken = localStorage.getItem("refreshToken");
    this.accountService.getNewToken(refreshToken).then(
      (res) => {
        if (res) {
          request = this._addToken(request, this.authService.getToken());
          return next.handle(request); // Don't perform the request intercepted 
        } else {
          this.router.navigate(["/login"]);
        }
      },
      (err) => {
        this.router.navigate(["/login"]);
      }
    );
  }

  _addToken(request: HttpRequest<any>, token: string) {
    return request.clone({
      setHeaders: {
        JWT_TOKEN: token,
      },
    });
  }
}

标签: javascriptangularangular-http-interceptors

解决方案


看起来你忘记了 return 声明。

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      catchError((error) => {
        if (error instanceof HttpErrorResponse && error.status === 403) {
          return this._handle403Error(request, next);
        }
        return throwError(error);
      })
    );
  }

_handle403Error(request: HttpRequest<any>, next: HttpHandler) {
    const refreshToken = localStorage.getItem("refreshToken");
    return from(this.accountService.getNewToken(refreshToken)).pipe(
        switchMap(res => {
            if (res) {
                request = this._addToken(request, this.authService.getToken());
                return next.handle(request); // Don't perform the request intercepted 
            }
            return from(this.router.navigate(["/login"])).pipe(switchMapTo(EMPTY));
        }),
        catchError(() => from(this.router.navigate(["/login"])).pipe(switchMapTo(EMPTY)),
    );
}

推荐阅读