首页 > 解决方案 > 在服务器响应 401 错误后使用拦截器附加正确的令牌

问题描述

我正在尝试为所有身份验证问题创建一个错误处理方法。我遇到了一个问题,正在调用我的 authTokenService.getAmadeusAuthToken$ 方法,但由于它是返回新令牌的后调用,因此需要更长的时间来解决,同时 catchError obvservable 在令牌之前返回 next.handle取回。我尝试了几种不同的方法,但我不知道让拦截器方法等到 authTokenService.getAmadeusAuthToken$ 完成的最佳方法。这是我的代码:

My Interceptor:

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      catchError((response: HttpErrorResponse) => {
        return next.handle(req).pipe(
          tap(test => {
            this.authTokenService.getAmadeusAuthToken$().pipe(
            ).subscribe(token => {
            const authReq = req.clone({
              headers: req.headers.append('Authorization', 'Bearer ' + token.access_token)
            });
            return next.handle(authReq);
            })
          })
        )
      })

发布调用以获取新令牌的方法

  getAmadeusAuthToken$():  Observable<any>{
const httpOptions = {  headers: new HttpHeaders().set('Content-Type', "application/x-www-form-urlencoded")}
return this.http.post<Token>('https://test.api.amadeus.com/v1/security/oauth2/token', this.body, httpOptions)

}

为了确保拦截方法正常工作,我进行了一个 API 调用来获取新令牌并将其硬编码。拦截方法的工作方式非常棒,因为没有竞争条件,并且拦截器返回 next.handle()立即获得令牌。

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      catchError((response: HttpErrorResponse) => {
         const authReq = req.clone({
              headers: req.headers.append('Authorization', 'Bearer ' + "lkVkfilWizfcuyVpXBQsA08XkUy5")
            });
        return next.handle(authReq);
      })

所以基本上我想确保拦截器等待 authTokenService.getAmadeusAuthToken$ 完成获取令牌,然后才返回带有令牌的新 next.handle,我在这里缺少什么?

标签: angularrxjsinterceptor

解决方案


Instead of returning next.handle(...), you actually want to return an observable that first calls to get a new token, then executes the next request.

To avoid subscribing we can use switchMap to handle the subscribing for us:

intercept(req: HttpRequest<any>, next: HttpHandler) {
    return this.authTokenService.getAmadeusAuthToken$().pipe(
        switchMap(token => {
            const headers = req.headers.set('Authorization', `Bearer ${token.access_token}`);
            const authReq = req.clone({ headers });

            return next.handle(authReq);
        })
    );
}

推荐阅读