簡體   English   中英

令牌攔截器不再發送原始請求(Angular、Node.js)

[英]Token interceptor does not send the original request again (Angular, Node.js)

我正在嘗試在我的 Angular 前端實現令牌攔截器,但我當前的實現存在一個問題。

我的攔截器如下所示:

  intercept(request: HttpRequest<any>,next: HttpHandler): Observable<HttpEvent<any>> {
    if (request.headers.get("No-Auth") === "True") {
      return next.handle(request);
    }

    return next.handle(request).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          this.handle404Error(request, next);
        } else {
          return throwError(error);
        }
      })
    );
  }

並處理404錯誤function:

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

      return this.authService.refreshToken().subscribe(
        (res: any) => {
          if (Boolean(res) === true) {
            this.isRefreshing = false;
            this.refreshTokenSubject.next(res);
            return next.handle(request);
          } else {
            return this.authService.logout();
          }
        },
        err => {
          return this.authService.logout();
        },
        () => {
          this.isRefreshing = false;
        }
      );
    } else {
      return this.refreshTokenSubject.pipe(
        filter(res => res != null),
        take(1),
        switchMap(() => {
          return next.handle(request);
        })
      );
    }
  }

當我進行 API 調用並且服務器返回 404 時,我的攔截器將調用/token端點以獲取新的 JWT。

Note that I am storing JWT in session object on server (in memory) and on client I have only sessionID and refresh token as HttpOnly cookies.

問題是,當我進行 API 調用並且 JWT 無效時,它將設置新的 JWT,但它不會再次發送先前的請求。 (在 JWT 過期后,我必須按兩次按鈕才能獲取數據)。

你有什么想法,如何實現這個邏輯?

謝謝你的幫助。

不正確的第一件事 - 你在攔截器中subscribe ,所以你得到嵌套訂閱,因為 Angular 在內部訂閱你的請求。

你真正想要的是返回你的return next.handle(request); catchError 例子:

return next.handle(request).pipe(
  catchError(error => {
    if (error instanceof HttpErrorResponse && error.status === 401) {
      return this.handle404Error(request, next);
    } else {
      return throwError(error);
    }
  })
);

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

    return this.authService.refreshToken().pipe(
      mergeMap((res: any) => {
        if (Boolean(res) === true) {
          this.isRefreshing = false;
          this.refreshTokenSubject.next(res);
          return next.handle(request);
        } else {
          /* return */ this.authService.logout();
          return of(undefined) // added this because I dont know what this.authService.logout() returns. It must be an Observable
        }
      }),
      catchError((err) => {
        /* return */ this.authService.logout();
        return throwError(err);
      }))      
  } else {
    return this.refreshTokenSubject.pipe(
      filter(res => res != null),
      take(1),
      switchMap(() => {
        return next.handle(request);
      })
    );
  }
}

請注意,我沒有檢查任何錯別字。 我也丟棄了這個塊:

() => {
  this.isRefreshing = false;
}

如果要在this.authService.refreshToken()完成時執行它,可以在mergeMapcatchError旁邊添加finalize運算符。

解釋這里實際發生的事情很簡單——你從intercept方法返回一個Observable。 只需 pipe 所有 API 一起調用並返回 stream 將執行它們。

暫無
暫無

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

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