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

Angular Token拦截器刷新JWT后仅重发最后一个401请求问题求解

Angular JWT令牌拦截器多请求401丢失问题修复

根因定位

你的代码核心逻辑错误出在handle401Error方法的分支处理上:

  • 当已经有请求触发令牌刷新(isRefreshing = true)时,后续进入该方法的401请求没有返回对应的Observable对象,直接被静默丢弃,所以只有第一个触发刷新的请求会被重发,其余请求全部丢失。
  • 等待刷新完成后重发请求的逻辑被错误放在了!isRefreshing分支内部,仅当刷新令牌为空时才会执行,完全不符合预期的业务逻辑。

修复代码

仅需要调整handle401Error方法的分支逻辑即可:

private handle401Error(request: HttpRequest<any>, next: HttpHandler, rToken: string) {
  if (!this.isRefreshing) {
    this.isRefreshing = true;
    this.refreshTokenSubject.next(null);

    if (rToken && rToken !== '') {
      const body = new URLSearchParams();
      body.set('grant_type', 'refresh_token');
      body.set('refresh_token', rToken);

      return this.authService.fetchToken$(body).pipe(
        switchMap((newToken: Token) => {
          this.isRefreshing = false;

          this.sessionStorageJwtService.setToken(newToken);
          this.refreshTokenSubject.next(newToken);

          return next.handle(this.addTokenHeader(request, newToken));
        }),
        catchError((err) => {
          this.isRefreshing = false;
          this.authFacade.logout();
          return throwError(err);
        })
      );
    } else {
      // 无有效刷新令牌直接触发登出
      this.isRefreshing = false;
      this.authFacade.logout();
      return throwError(() => new Error('无可用刷新令牌'));
    }
  } else {
    // 刷新过程中产生的所有401请求,等待新令牌生成后统一重发
    return this.refreshTokenSubject.pipe(
      filter(token => token !== null),
      take(1),
      switchMap((token) => next.handle(this.addTokenHeader(request, token)))
    );
  }
}

额外优化建议

你当前获取令牌和刷新令牌的逻辑是通过subscribe订阅Observable取值,若SessionStorageJwtService的取值逻辑是异步的,可能存在取值延迟导致后续判断出错的问题,建议改为直接读取sessionStorage的同步接口取值,避免异步问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:39:05