简体   繁体   English

防止在Angular 2中多次调用Access Token API

[英]Prevent multiple calls to Access Token API in Angular 2

I am developing an application in Angular 2 in which there are multiple API calls made at different time periods. 我正在Angular 2中开发一个应用程序,其中在不同时间段进行了多个API调用。

The problem arises when the Access token has expired and needed to be refreshed. 当访问令牌已过期并且需要刷新时,就会出现问题。

For every API call, I am checking the token status. 对于每个API调用,我都会检查令牌状态。

When the token has expired the Access token API will be called after which the actual API calling will be executed. 当令牌到期时,将调用访问令牌API,之后将执行实际的API调用。

This feature works fine when there is only one API call. 只有一个API调用时,此功能可以正常使用。

But, when there are N number of API calls when the token has expired, the access token API also gets called N times. 但是,当令牌到期时有N个API调用时,访问令牌API也将被调用N次。

Here is how the current process is, 这是当前的过程,

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

If there are multiple API calls at the time of Token expiration, the Token header and body construction processes gets executed and even before the Token API responds, the other APIs call the token API. 如果令牌到期时有多个API调用,则将执行Token标头和主体构造过程,甚至在Token API响应之前,其他API也会调用令牌API。

Angular prevent multiple token refresh on asynchronous requests Angular防止异步请求刷新多个令牌

I tried with the above answer but as our function returns Observable, it states that Promise is not assignable to Observable. 我尝试使用上面的答案,但是由于我们的函数返回Observable,因此它指出Promise无法分配给Observable。

I came across many examples of queuing the API requests but none yielded the desired result. 我遇到了许多使API请求排队的示例,但是都没有产生期望的结果。

How to queue the calling APIs when there is a call for Token API which is yet to respond and then continue with the queuing APIs? 当对令牌API的调用尚未响应然后如何继续使用排队API时,如何使调用API排队?

In this case, when there is already a call to Access token API and when it has returned, the waiting APIs should go to the else part. 在这种情况下,当已经存在对Access令牌API的调用并返回时,正在等待的API应该转到else部分。

Kindly help me with this. 请帮助我。 Thank you. 谢谢。

According to your demand - here is a snippet of HttpInterceptor implementation with a context of token management: Notice that for a better separation of concerns i used: 根据您的需求-这是带有令牌管理上下文的HttpInterceptor实现的摘要:请注意,为了更好地分离关注点,我使用了:

A general authService which is the one the responsible for the token management (asking from server , saving in cache, etc'). 一种通用的authService,它负责令牌管理(从服务器询问,保存在缓存中等)。

An action manager - responsible to take the decision where to go next. 行动经理-负责决定下一步行动。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM