如何在Angular7中获取另一个请求的响应时调用HTTP请求?

时间:2019-06-15 11:22:48

标签: angular typescript jwt angular2-jwt

这种情况是在后端调用服务时,如果我收到错误代码表示该服务已过期,则在前端 首先:请求有效的jwt令牌。 第二:在获得有效令牌后重新请求原始的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请求类型的内容)。

我是新手,所以我希望我能提供足够的信息来解决问题。

2 个答案:

答案 0 :(得分:0)

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
      }
    }
    ));
  }

上面的代码片段,如果有错误,将重试,它将首先刷新令牌,返回一个可观察的对象,然后再次调用getAll。

答案 1 :(得分:0)

此解决方案受此答案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;
        }
      })
    );
  }