【问题标题】:Prevent multiple calls to Access Token API in Angular 2防止在 Angular 2 中多次调用访问令牌 API
【发布时间】:2018-08-02 06:07:44
【问题描述】:

我正在使用 Angular 2 开发一个应用程序,其中在不同时间段进行了多个 API 调用。

当访问令牌已过期并需要刷新时,就会出现问题。

对于每个 API 调用,我都会检查令牌状态。

当令牌过期时,将调用访问令牌 API,之后将执行实际的 API 调用。

当只有一个 API 调用时,此功能可以正常工作。

但是,当令牌过期时有 N 次 API 调用时,访问令牌 API 也会被调用 N 次。

这是当前的流程,

postRequest(url, body, header): Observable<Object> {
    //Computation of Access token status
    if (needToken) {
        //Token header and body construction
        return this.http.post(token_url, token_body, token_header).map(
            (res: Response) => {
                //Token Success
            }
        )
        .flatMap(
                success =>
                    this.http.post(url, body, header)  //Actual API
        )
        .map((res: Response) => {
            //Actual API Success
        }
    }
    else {
        return this.http.post(url, body, header).map(
            (res: Response) => {
                //API Success
            }
        )
    }
}

如果在 Token 到期时有多个 API 调用,Token 头部和主体构造过程会被执行,甚至在 Token API 响应之前,其他 API 都会调用令牌 API。

Angular prevent multiple token refresh on asynchronous requests

我尝试了上面的答案,但是当我们的函数返回 Observable 时,它​​表明 Promise 不能分配给 Observable。

我遇到了许多排队 API 请求的示例,但没有一个产生预期的结果。

当令牌API调用尚未响应时,如何将调用API排队,然后继续排队API?

在这种情况下,当已经有访问令牌 API 的调用并返回时,等待的 API 应该转到 else 部分。

请帮我解决这个问题。谢谢。

【问题讨论】:

  • 你考虑过实现 HttpInterceptor 吗? (例如令牌拦截器服务)如果根据来自服务器(401)的状态遇到未经授权的调用,它将执行正确的操作?如果你想让我加你一个 sn-p,请告诉我。
  • @Rotemya 不,我没有尝试过使用 HttpInterceptor。请添加片段。
  • 你也可以试试 Rxjs 和 retryWhen,你可以检查错误是否是 token 过期。您可以重试相同的 API 调用。
  • @Kaushik 你找到解决方案了吗?这是http类中的一个真正问题。因为我们不能在角度较低的版本中使用 httpHandler 类

标签: angular api http


【解决方案1】:

根据您的需求 - 这是一个带有令牌管理上下文的 HttpInterceptor 实现的 sn-p:请注意,为了更好地分离我使用的关注点:

一个通用的 authService 负责令牌管理(从服务器询问、保存在缓存中等)。

行动经理 - 负责决定下一步去哪里。

import { Injectable } from '@angular/core';

import {HttpRequest,HttpHandler,HttpEvent,HttpInterceptor , HttpResponse , HttpErrorResponse} from '@angular/common/http';
import {Observable} from "rxjs";
import {tap} from "rxjs/operators";

import {HttpHandlerService} from "../../http-handler.service";
import {ActionsService} from "../../../actions/actions.service";
import {AuthService} from "../../../../core/auth/auth.service";


@Injectable({
  providedIn: 'root'
})
export class TokenInterceptorService implements HttpInterceptor{

  constructor(
    private _actionsManager : ActionsService,
    private _authService    : AuthService
  ) {}

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

    //Part 1 - adding headers - only for relevant apis
    var accessToken = this._authService.getToken();
    let authorizationHeader = accessToken ?
    {'Authorization' : 'Bearer ' + accessToken                       , 'content-type' : 'application/json'}:
    {'Authorization' : 'Basic '  + this._authService.getBasicToken() , 'content-type' : 'application/x-www-form-urlencoded'};

    request = request.clone({
      setHeaders: authorizationHeader
    });

    //Part 2 - handling request and responses
    return next.handle(request).pipe(
      tap(
        (event: HttpEvent<any>) => {
          if (event instanceof HttpResponse) {
            // do stuff with response if you want
          }
        },
        (err: any) => {
          if (err instanceof HttpErrorResponse) {
            if (err.status === 401 || err.status === 403) {
                               this._actionsManager.onEvent("unAuthorizedResponseFromServer");
            }
          }
        }
      )
    );
  }

}

【讨论】:

  • 感谢Rotemya。但是,我的 Angular 版本是 1.1.0。因此,我无法使用 HttpInterceptor。您是否熟悉任何不使用 HttpInterceptor 的解决方法?
  • 更正:我的 Angular 版本是 4.4.6。我使用 Http 而不是 HttpClient。所以不能使用HttpInterceptor。请提出一种在没有 HttpInterceptor 的情况下实现该功能的方法。
  • 4.4.6 版很棒 - Http 拦截器已经在 Angular 4.3.4 中实现。上面的代码应该适合你。
  • 是的,我可以看到。但是,我没有使用过 HttpClient。 Http 被用于触发 Post 请求。
  • @Kaushik,我不确定我是否理解。在我的示例中,什么不适合您?
猜你喜欢
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 2020-10-13
  • 2018-04-12
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
相关资源
最近更新 更多