![](/img/trans.png)
[英]angular http interceptor not calling request again after token refresh
[英]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()
完成時執行它,可以在mergeMap
和catchError
旁邊添加finalize
運算符。
解釋這里實際發生的事情很簡單——你從intercept
方法返回一個Observable。 只需 pipe 所有 API 一起調用並返回 stream 將執行它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.