【问题标题】:How to call HTTP request while getting the response of another one in Angular7?如何在 Angular7 中获取另一个响应的同时调用 HTTP 请求?
【发布时间】:2019-10-29 18:47:12
【问题描述】:

这种情况是在后端调用服务时,如果我收到错误代码表明它已过期,那么在前端 首先:请求一个有效的 jwt 令牌。 第二:获取有效token后重新请求原始http请求。 第一步已成功完成,但第二步并非如此。 这是拦截器中的代码

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {


    if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
      request = this.addAuthenticationToken(request);
    }
    return next.handle(request).pipe(catchError(err => {
      Log.log("Error Status: " + err.status);
      // invalid token or bad request
      if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
        this.authenticationService.logOut();
        return EMPTY;
      }
      else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
        this. doRefreshToken(request, next);
      }
    }
    ));
  }

doRefreshToken(request, next) {
    return this.authenticationService.refreshToken().subscribe((resp: HttpResponse<any>) => {
      Log.log("in subscripe refresh token")
      Log.log(resp.headers.get(this.AUTH_HEADER));
      StorageManagementUtil.setLocaltStorage(resp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>resp.body);
    },
      (error) => { Log.log(error) },
      () => {
        Log.log("on complete()")
        request = this.addAuthenticationToken(request);
        return next.handle(request);
      });
  }

这是刷新令牌服务

refreshToken() {
    let map = new TSMap();
    map.set(this.RQUEST_BODY_KEY_SESSION_TOKEN, StorageManagementUtil.readFromLocalStorage(StorageManagementUtil.SESSION_TOKEN));
    var requsetBody = JSON.stringify(map.toJSON());
    let request = new PortalRequestTransaction(requsetBody);
    return this.http.post<PortalRsponseTransaction>(fullURL, request, {
      observe: 'response',
      responseType: 'json'
    });
  }

这是检查时网络点击的屏幕截图

https://i.ibb.co/vqLTLh2/1.png

问题是为什么在获取刷新令牌后调用原始服务没有完成?为什么调用服务要执行两次? (如果我们忽略 OPTIONS 请求类型的那些)。

我是 Angular 的初学者,所以我希望我能提供足够的信息来找出问题所在。

【问题讨论】:

    标签: angular typescript jwt angular2-jwt


    【解决方案1】:

    1) 401 表示未经授权,您似乎没有在请求中发送正确的授权标头(Bearer {JWT-Token} )。

    2) 对于刷新令牌,最好使用 rxjs-retry ,这将帮助您处理错误或到期时的刷新逻辑

    代码如下:

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
    
        if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
          request = this.addAuthenticationToken(request);
        }
        return next.handle(request).pipe(
        retryWhen(err => {
         if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
           return this. doRefreshToken(request, next);
          }
        }),
        catchError(err => {
          Log.log("Error Status: " + err.status);
          // invalid token or bad request
          if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
            this.authenticationService.logOut();
            return EMPTY;
          }
          else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
            this. doRefreshToken(request, next); // return an observable
          }
        }
        ));
      }
    

    上面的代码sn-p,如果有错误会重试,它会先刷新token,返回一个observable,然后再次调用getAll。

    【讨论】:

    • 1) 我从后端返回 401 表示令牌已过期。错误状态码不会影响代码的行为。 2)我需要在请求刷新令牌后重试并将新的有效令牌添加到原始请求的标头中,所以我认为 rxjs-retry 不会有用。
    • 感谢您的帮助,我尝试了您的解决方案,但由于某种原因,它不间断地运行。我已经发布了适用于我的情况的代码。
    【解决方案2】:

    这个解决方案的灵感来自这个答案using switchMap

     intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
          request = this.addAuthenticationToken(request);
        }
        return next.handle(request).pipe(
          catchError((err) => {
            // invalid token or bad request
            if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
              this.authenticationService.logOut();
              return EMPTY;
            }
            else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) {
              return this.handleRefreshToken(request, next);
            }
          })
        );
      }
    
    
      handleRefreshToken(request: HttpRequest<any>, next: HttpHandler) {
    
        return this.authenticationService.refreshToken().pipe(
          switchMap((tokenResp) => {
            StorageManagementUtil.setLocaltStorage(tokenResp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>tokenResp.body);
            request = this.addAuthenticationToken(request);
            return next.handle(request);
          }),
          catchError(error => {
            if (error.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
              this.authenticationService.logOut();
              return EMPTY;
            }
          })
        );
      }
    

    【讨论】:

      猜你喜欢
      • 2018-04-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-20
      • 2020-03-14
      • 2019-12-22
      • 2012-05-25
      • 2011-12-21
      • 1970-01-01
      相关资源
      最近更新 更多