【问题标题】:Request new access token and continue last request请求新的访问令牌并继续上次请求
【发布时间】:2020-06-01 07:07:53
【问题描述】:

我正在使用 Angular / Typescript。应用程序与 API 通信,access_token 存储在存储中。

对于每个请求,拦截器都会检查access_token 是否仍然有效。

当access_token过期时,应用需要用refresh_token刷新access_token并继续上一个请求(用新的access_token

问题 我无法克隆原始请求(使用过期令牌)并执行它。 请求新的access_token 的调用干扰了拦截器。 最好的方法是:

  1. 请求新令牌。
  2. 设置新令牌。
  3. 恢复具有过期令牌和克隆的调用以成功运行?

拦截器:

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // add authorization header with jwt token if available
        if (!this.isRefreshing) {
            if (this.authenticationService.checkLoginState()) {
                // Check if access_token is valid.
                this.currentUser = JSON.parse(localStorage.getItem('auth'));
                if (new Date(this.currentUser.access_token_expires) > new Date()) {
                    // Access token is valid, clone request and continue.
                    request = request.clone({
                        setHeaders: {
                            Authorization: `Bearer ${this.currentUser.access_token}`
                        }
                    });
                    return next.handle(request);
                } else {
                    // Token is not valid, request new token with reLogin().
                    this.reLogin().then(any => {
                        // New token has been set, now run old request with new token.
                        return next.handle(request);
                    }, error => {
                        this.authenticationService.logout();
                    });
                }
            }
        } else {
            return next.handle(request);
        }
    }

重新登录:

    reLogin() {
        return new Promise(function (resolve, reject) {
            this.isRefreshing = true;
            // Check if refresh token is valid
            if (new Date(this.currentUser.refresh_token_expires) > new Date()) {
                this.authenticationService.loginWithRefreshToken(this.currentUser.refresh_token).subscribe(data => {
                    // Using refresh_token was successful
                    this.currentUser = JSON.parse(localStorage.getItem('auth'));
                    this.isRefreshing = false;
                    resolve();
                }, error => {
                    console.error(error);
                    reject();
                });

        });
    }

【问题讨论】:

  • 在拦截器中创建一个 if 语句以避免 httpRequest 具有 refreshtoken URL。我不知道这是否是一个好方法。但我使用的是相同的
  • 我有一个 if 语句 ( if (!this.isRefreshing) ) 在请求新令牌时该值设置为 true。
  • 我不确定它(isRefreshing)是否在维护状态尝试从request.url.includes('refreshToken')检查它(给出API的url)
  • 我把isRefreshing改成了url,结果还是一样。下一个电话正在尝试运行,但给了我错误:TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

标签: angular typescript angular-http-interceptors


【解决方案1】:

首先要注意的是,在克隆请求时为请求创建一个新的 const,而不是将其分配给旧的。 我认为的问题是,当您调用 reLogin 并期望在then 中您可以使用更新的令牌访问新请求时。但是您仍然处于旧 request 的上下文中。因此,您可能应该从reLogin 返回access_token,并将其设置在请求的克隆上,然后再继续处理。

【讨论】:

    猜你喜欢
    • 2019-12-03
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2013-02-17
    • 2020-07-05
    • 2020-11-01
    • 1970-01-01
    相关资源
    最近更新 更多