简体   繁体   English

Angular 7 中的 JWT 刷新令牌 - API 在 HTTP 拦截器中多次调用

[英]JWT Refresh Token in Angular 7 - API's calling multiple times in HTTP interceptor

I am implementing JWT refresh token in my angular project.我正在我的 angular 项目中实现 JWT 刷新令牌。 I am following the below guide for that.我正在遵循以下指南。

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

Here is my code:这是我的代码:

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;
}

Btw.顺便提一句。 the reason I am not doing this inside catchError is because our backend is structured like it will always send HTTP status code 200 and inside that response they will send custom http code based on error such as 401, 500 or success such as 200 and etc. So it won't go inside catchError since it looks for HTTP status codes other than 200.我不在catchError这样做的原因是因为我们的后端的结构就像它总是发送 HTTP 状态代码 200 而在该响应中,他们将根据错误(例如 401、500 或成功(例如 200 等)发送自定义 http 代码)。因此它不会进入catchError内部,因为它会查找 200 以外的 HTTP 状态代码。

Now my issue is after implementing the inceptor now my API's getting called multiple times.现在我的问题是在实现了 inceptor 之后,我的 API 被多次调用。 See screenshot below:请看下面的截图:

在此处输入图片说明

Been stuck since yesterday and haven't found any proper solution yet.从昨天开始就卡住了,还没有找到任何合适的解决方案。 Would be great if anyone could point what I am doing here and how do I solve it?如果有人能指出我在这里做什么以及我该如何解决,那就太好了?

If you have any further query, do let me know.如果您有任何进一步的疑问,请告诉我。 Thank you..谢谢..

A tip for:提示:

Btw.顺便提一句。 the reason I am not doing this inside catchError is because our backend is structured like it will always send HTTP status code 200 and inside that response they will send custom http code based on error such as 401, 500 or success such as 200 and etc. So it won't go inside catchError since it looks for HTTP status codes other than 200.我不在 catchError 中这样做的原因是因为我们的后端的结构就像它总是发送 HTTP 状态代码 200 而在该响应中,他们将根据错误(例如 401、500 或成功(例如 200 等)发送自定义 http 代码)。因此它不会进入 catchError 内部,因为它会查找 200 以外的 HTTP 状态代码。

You can do a map in the response from the server and check if theres an error, and then throw an error from there, then catchError should work on sequent pipes.您可以在来自服务器的响应中做一个映射并检查是否有错误,然后从那里抛出错误,然后 catchError 应该在后续管道上工作。

The error is because you are returning the handle in the switchMap making the request being called again.错误是因为您正在返回 switchMap 中的句柄,从而再次调用请求。

return next.handle(req);

Change that line to:将该行更改为:

return of(event)

And it should work它应该工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM