【问题标题】:Calling an async function in an Angular interceptor class在 Angular 拦截器类中调用异步函数
【发布时间】:2019-12-16 18:33:43
【问题描述】:

我正在使用 AWS Cognito 对 Angular 应用程序中的用户进行身份验证。我想在会话到期之前每小时自动刷新一次。

我们使用 Angular 拦截器类在每个请求的标头中设置访问令牌。当用户登录时,时间被保存并存储在本地存储中。在每次 HTTP 请求之前都会检查这一点,如果周期大于一小时,请从 amazon-cognito-identity-js 库中调用 cognito 用户池 refreshSession 函数。

但是,这种方法似乎无法无缝刷新会话。我已经能够刷新会话,但是正在进行的调用返回 401,并且只有在此之后才会刷新会话。

拦截器如下所示:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const invalid = this.checkSessionNotValidViaStorage();
    if (invalid) {
      return from(this.authenticationService.refreshSessioFromPromise()).pipe(result => {
        const newRequest = this.setHeader(request);
        return next.handle(newRequest);
      });
    } else {
      const newRequest = this.setHeader(request);
      return next.handle(newRequest);
    }
}

身份验证服务如下所示:

refreshSessioFromPromise(): Observable<string> {
    return from((resolve: any, reject: any) => {
      const currentUser = this.getCurrentUser();
      currentUser.getSession((getSessionErr: any, getSessionSession: any) => {
        const refreshToken = getSessionSession.getRefreshToken();
        currentUser.refreshSession(refreshToken, (refreshSessionErr, refreshSessionSession) => {
          if (refreshSessionErr) {
            reject('Cognito: Can not set the credentials:' + refreshSessionErr);
          } else {
            this.setCredentials(refreshSessionSession, this.remember);
            this._credentials = refreshSessionSession;
            resolve('Cognito: refreshed successfully');
          }
        });
      });
    });
}

这种使用 RxJs from 函数的方法基于the article by Michael Karén Michael Karén

我也尝试过使用 Promise 和其他 RxJs 方法。似乎 amazon-cognito-identity-js 库正在放弃异步球,所以最大的问题是如何确保在允许更多调用继续之前刷新会话。

可能使用拦截器不是正确的方法,需要在 HTTP 服务之上再增加一层来完成此操作。

任何关于正确的 RxJs/Angular 拦截器方法或其他更好方法的帮助将不胜感激。

【问题讨论】:

    标签: angular rxjs amazon-cognito interceptor


    【解决方案1】:

    错误在于拦截功能。像这样重构它:

    from(this.authenticationService.refreshSessioFromPromise()).pipe(
      switchMap(result => {
        const newRequest = this.setHeader(request);
        return next.handle(newRequest);
      })
    )
    

    管道函数需要一个 RxJS 操作符。在这种情况下,我们应该从 auth 服务的 observable 获取返回值,并切换到 next.handle 调用返回的 observable。

    因为我们要从一个 observable 转到另一个 observable,所以我们需要使用展平运算符。转换为 observables 的 Promise 发出一个值,然后完成。这意味着我们不必担心扁平化策略,使用简单的switchMap 就可以了。如果您对其他扁平化策略感到好奇,请查看concatMapexhaustMapmergeMap 运算符,

    【讨论】:

      猜你喜欢
      • 2020-11-08
      • 2018-09-08
      • 1970-01-01
      • 2018-03-31
      • 1970-01-01
      • 2018-07-08
      • 2022-08-04
      • 2019-10-15
      • 1970-01-01
      相关资源
      最近更新 更多