【问题标题】:JWT Refresh Token in Angular 7 - API's calling multiple times in HTTP interceptorAngular 7 中的 JWT 刷新令牌 - API 在 HTTP 拦截器中多次调用
【发布时间】:2021-03-01 12:23:03
【问题描述】:

我正在我的 Angular 项目中实现 JWT 刷新令牌。我正在遵循以下指南。

https://angular-academy.com/angular-jwt/

这是我的代码:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const user: any = this.storage.user;
    const addToken = !req.urlWithParams.includes('token');
    const token = user ? user.token : null;

    if (token && !req.url.includes('token=') && addToken) {
        req = this.addToken(req, user.token);
    }

    return next.handle(req).pipe(switchMap((event) => {
        if (event instanceof HttpResponse && event.body.code === 401 && token) {
            return this.handle401Error(req, next);
        }
        return next.handle(req);
    }));
}


private addToken(request: HttpRequest<any>, token: string) {
    return request.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
      setParams: {
        token
      }
    });
}


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

    return this.getRefreshedJWT().pipe(
      switchMap((res: any) => {
        this.isRefreshing = false;
        this.refreshTokenSubject.next(res.token);
        return next.handle(this.addToken(request, res.token));
      }));

  } else {
    return this.refreshTokenSubject.pipe(
      filter(token => token != null),
      take(1),
      switchMap(jwt => {
        return next.handle(this.addToken(request, jwt));
      }));
  }
}


getRefreshedJWT() {
  const jwt_refresh_url = 'api/v3/token/refresh?token=' + this.storage.user.token;
  
  return this.http.getFromAccountsApi(jwt_refresh_url)
      .pipe(tap((token) => {
      this.storeJwtToken(token);
  }));
}


private storeJwtToken(jwt: string) {
  const user = this.storage.user;
  user.token = jwt;
  this.storage.user = user;
}

顺便说一句。我没有在catchError 内部这样做的原因是因为我们的后端的结构就像它总是发送 HTTP 状态代码 200 并且在该响应中他们将根据错误(例如 401、500 或成功(例如 200)发送自定义 HTTP 代码和等等。所以它不会进入catchError,因为它会查找 200 以外的 HTTP 状态代码。

现在我的问题是在实现了 inceptor 之后,我的 API 被多次调用。请看下面的截图:

从昨天开始就被卡住了,还没有找到任何合适的解决方案。如果有人能指出我在这里做什么以及如何解决它,那就太好了?

如果您还有任何疑问,请告诉我。谢谢。。

【问题讨论】:

  • "我们的后端的结构就像它总是发送 HTTP 状态代码 200 并且在该响应中,他们将根据错误(例如 401、500 或成功(例如 200 等)发送自定义 HTTP 代码) ." - 屏蔽状态响应不是一个好习惯..
  • @iLuvLogix 我理解,但对此无能为力。这是一个企业应用程序,他们已经这样做了 3-4 年。这就是他们构建后端的方式。

标签: javascript angular typescript rxjs jwt


【解决方案1】:

提示:

顺便说一句。我没有在 catchError 中执行此操作的原因是因为我们的后端的结构就像它总是发送 HTTP 状态代码 200 并且在该响应中它们将根据错误(例如 401、500 或成功(例如 200 等)发送自定义 HTTP 代码)。因此它不会进入 catchError 内部,因为它会查找 200 以外的 HTTP 状态代码。

您可以在服务器的响应中做一个映射并检查是否有错误,然后从那里抛出一个错误,然后 catchError 应该在后续管道上工作。

错误是因为您在 switchMap 中返回句柄,从而再次调用请求。

return next.handle(req);

将该行更改为:

return of(event)

它应该可以工作

【讨论】:

    猜你喜欢
    • 2017-12-31
    • 2018-06-12
    • 2019-03-28
    • 2017-12-26
    • 2019-09-03
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多