簡體   English   中英

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

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

我正在我的 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 被多次調用。 請看下面的截圖:

在此處輸入圖片說明

從昨天開始就卡住了,還沒有找到任何合適的解決方案。 如果有人能指出我在這里做什么以及我該如何解決,那就太好了?

如果您有任何進一步的疑問,請告訴我。 謝謝..

提示:

順便提一句。 我不在 catchError 中這樣做的原因是因為我們的后端的結構就像它總是發送 HTTP 狀態代碼 200 而在該響應中,他們將根據錯誤(例如 401、500 或成功(例如 200 等)發送自定義 http 代碼)。因此它不會進入 catchError 內部,因為它會查找 200 以外的 HTTP 狀態代碼。

您可以在來自服務器的響應中做一個映射並檢查是否有錯誤,然后從那里拋出錯誤,然后 catchError 應該在后續管道上工作。

錯誤是因為您正在返回 switchMap 中的句柄,從而再次調用請求。

return next.handle(req);

將該行更改為:

return of(event)

它應該工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM