0

这种情况是在后端调用服务时,如果我收到错误代码表明它已过期,那么在前端首先:请求一个有效的 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 请求类型的那些)。

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

4

2 回答 2

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

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

于 2019-06-15T12:02:50.820 回答
0

这个解决方案的灵感来自这个使用 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;
        }
      })
    );
  }
于 2019-06-16T21:45:36.460 回答