You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular5+ngx-restangular:多过期令牌重复刷新令牌问题

解决Angular 5 + ngx-restangular并发请求时的令牌刷新重复问题

这个问题我之前做项目时也踩过坑,本质就是并发请求触发了重复的令牌刷新操作——当两个请求同时返回401未授权时,各自都去发起刷新令牌的请求,第一个请求拿到新令牌后重试成功,但第二个请求的刷新请求要么因为后端拒绝重复刷新(比如刷新令牌只能用一次),要么因为本地状态混乱直接失败。

核心思路很明确:把刷新令牌的请求变成一个共享的可观察对象,确保同一时间只有一个刷新请求在执行,其他需要刷新令牌的请求都等待这个请求完成后,用新令牌重试。

下面是具体的实现步骤:

1. 在Restangular配置服务中维护刷新请求缓存

首先在你的Restangular配置服务里,加一个变量来保存正在进行的刷新请求,避免重复发起:

// 用来缓存正在进行的刷新令牌请求
private refreshTokenRequest: Observable<any> | null = null;

2. 重写错误拦截逻辑,加入并发控制

在setErrorInterceptor里,不要直接触发刷新,先检查是否已有刷新请求在进行:

RestangularProvider.setErrorInterceptor((response, subject, responseHandler) => {
  // 只处理401未授权的场景
  if (response.status === 401) {
    // 检查是否已经有刷新请求在执行
    if (!this.refreshTokenRequest) {
      // 如果没有,发起刷新令牌请求并缓存这个Observable
      this.refreshTokenRequest = this.authService.refreshToken()
        .pipe(
          tap((newTokens) => {
            // 更新本地存储的新访问令牌
            this.authService.updateAccessToken(newTokens.accessToken);
            // 刷新完成后清空缓存,确保下一次过期能正常发起新请求
            this.refreshTokenRequest = null;
          }),
          catchError((error) => {
            // 刷新失败时清空缓存,并处理登出逻辑
            this.refreshTokenRequest = null;
            this.authService.logout();
            return throwError(() => error);
          })
        );
    }

    // 所有需要刷新的请求都订阅这个共享的刷新Observable
    this.refreshTokenRequest.subscribe({
      next: () => {
        // 用新令牌克隆并重发原请求
        const newRequest = response.request.clone({
          setHeaders: {
            Authorization: `Bearer ${this.authService.getAccessToken()}`
          }
        });
        // 将重发请求的结果传给原请求的subject
        this.http.request(newRequest).subscribe(subject);
      },
      error: (err) => {
        subject.error(err);
      }
    });

    // 返回false,告诉Restangular不要执行默认的错误处理逻辑
    return false;
  }

  // 其他错误交给默认处理流程
  return true;
});

3. 配合后端确保刷新接口的幂等性(可选但推荐)

和后端开发同学确认:刷新令牌的接口是否支持并发调用?如果后端限制一个刷新令牌只能用一次,那上面的缓存逻辑就更关键了——它能从根源上避免重复发送刷新请求。

关键原理说明

  • 第一个触发401的请求会发起刷新请求,并把这个Observable缓存起来
  • 后续的401请求不会再发新的刷新请求,而是直接订阅已有的那个Observable
  • 刷新完成后,所有等待的请求都会用新令牌重试,同时清空缓存,不影响下一次令牌过期的处理

这样不管同时有多少个请求触发401,都只会有一个刷新请求被发送,完美解决你遇到的并发场景问题。

内容的提问来源于stack exchange,提问作者Vahid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:23:32