【问题标题】:On Access token expiration make other APIs wait before new Access token is fetched在访问令牌到期时,让其他 API 在获取新的访问令牌之前等待
【发布时间】:2019-01-10 23:30:43
【问题描述】:

我的要求是实现一个Http post方法函数,其中,

  • 如果有 API 调用,它应该简单地执行它。
  • 但是,如果访问令牌已过期并且有 API 调用,则应首先调用访问令牌 API。在它响应并获取新令牌之前,实际的 API 应该等待。

访问令牌过期时调用的 API 数量会有所不同。所以任何数量的 API 都应该排队。

注意: 访问令牌在客户端验证时被声明为“过期”。实际访问令牌过期时间将在服务器上设置。

如何做到这一点?一个简单的例子将不胜感激。提前谢谢你。

【问题讨论】:

    标签: angular api typescript http


    【解决方案1】:

    遇到了同样的问题。我按照这里的描述解决了它:https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/

    【讨论】:

    • 我的 Angular 版本是 1.1.0。 HttpInterceptor 会起作用吗?
    • 拦截器也可以在angularjs中使用:docs.angularjs.org/api/ng/service/$http#interceptors但是这个解决方案是基于angular 2+,如果它以同样的方式与angularjs一起工作,我不知道。
    • 网站声明了这一点,*这里要注意的重要一点是,您必须使用从@angular/common/http 导入的 HttpClient(Angular 4.3+ 中的新功能)*“经典”http 客户端不会触发 HttpInterceptor 所以,我认为 Interceptor 不会在其他 API 上检测到 401 响应。
    • 更正:我的 Angular 版本是 4.4.6。我使用 Http 而不是 HttpClient。所以不能使用HttpInterceptor。请提出一种在没有 HttpInterceptor 的情况下实现该功能的方法。
    • 如果你使用 Http ,你需要扩展类并提供你的自定义实现来覆盖请求部分。另一方面,升级到 Angular 6 并更改为 HttpClient 并不难。要扩展 Http 类,请看这里:stackoverflow.com/questions/39675806/…
    【解决方案2】:

    请查找示例实现

     intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.sharedAPIProvider = this.inj.get(SharedAPIProvider);
    
    
        this.assetupdateArry = { users : 'getUserById' };
        return new Observable<HttpEvent<any>>((subscriber) => {
    
          // first try for the request
          next.handle(req)
            .timeout(API_TIMEOUT)
            .subscribe(
            (event: HttpEvent<any>) => {
              if (event instanceof HttpResponse) {
                // console.log('success from interceptr');
                      subscriber.next(event);
                subscriber.complete();
              }
            },
            (error) => {
              if (error instanceof HttpErrorResponse) {
    
                const requestUrl = this.checkUrl(error, sessionAvoidUrls); 
                if (requestUrl && error.status === 401) {
                  console.log('401 error, trying to re-login');
    
                  // If more then 10 retry cancel request
                  if (this.loginApiRetry > RE_AUTH_COUNT) {
                    this.loginApiRetry = 0;
                    subscriber.error(error);
                  } else {
                    this.loginApiRetry = this.loginApiRetry + 1;
                    this.resetLoginAPICount();
                    // console.log(this.loginApiRetry);
                    // try to re-log the user
                    this.sharedAPIProvider.reLogin().then((loginResp: any) => {
                      // re-login successful -> create new headers with the new auth token
                      if (loginResp !== undefined) {
                        this.events.publish('loginuser:update', loginResp);
                        const authToken = loginResp.response.authToken;
                        const newRequest = req.clone({
                          headers: req.headers.set('Authorization', authToken),
                        });
                        this.storageProvider.set('authToken', authToken);
    
                        // retry the request with the new token
                        next.handle(newRequest)
                          .timeout(API_TIMEOUT)
                          .subscribe(
                          (newEvent) => {
                            if (newEvent instanceof HttpResponse) {
                              // the second try went well and we have valid response
                              // give response to user and complete the subscription
                              subscriber.next(newEvent);
                              subscriber.complete();
                            }
                          },
                          (newError) => {
                            // second try went wrong -> throw error to subscriber
                            subscriber.error(newError);
                          });
                      } else {
                        this.events.publish('user:relogin');
                      }
                    });
                  }
                }  else {
                  subscriber.error(error);
                }
              } else {
                // the error was not related to auth token -> throw error to subscriber
                subscriber.error(error);
              }
            });
        });
      }
    

    【讨论】:

    • Rahul,我的 Angular 版本是 1.1.0。我不认为 HttpInterceptor 不会被触发。
    • OK Kaushik 这个例子是针对 angular5 的。即使在 angular 1 拦截器中,我们也可以实现我将更新相同
    • 好的,拉胡尔。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    • 2021-11-16
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多