在不持續登入的情況下維持使用者會話是流暢網路體驗的關鍵。在這篇部落格中,我將向您展示如何在 Angular 中實作令牌刷新工作流程,處理 401 錯誤並有效管理並發請求。
在身分驗證系統中,存取權杖的生命週期較短,可以最大限度地降低安全風險。當存取令牌過期時,刷新令牌允許應用程式從伺服器請求新的存取令牌,而不需要使用者再次登入。
我們將使用 Angular 的 HttpInterceptor 實作刷新令牌機制。目標是攔截未經授權的請求(401 錯誤)並在重試原始請求之前刷新令牌。
請求攔截:
攔截器偵測到 401 未經授權的回應。
令牌刷新:
如果令牌過期,refreshToken 會取得新令牌。
重試請求:
使用新令牌重試原始請求。
隊列管理:
刷新令牌後,將處理待處理的請求。
handleUnauthorized( req: HttpRequest<any>, next: HttpHandlerFn ): Observable<any> { if (!this.isRefreshingToken) { this.isRefreshingToken = true; // Notify all waiting requests that the token is being refreshed this.tokenSubject.next(null); return this.refreshToken().pipe( switchMap((newToken: string) => { if (newToken) { this.tokenSubject.next(newToken); // Retry the original request with the new token return next(this.addToken(req, newToken)); } // If token refresh fails, log out the user this.logout(); return throwError(() => 'Token expired'); }), catchError((error) => { this.logout(); // Log out on error return throwError(() => error); }), finalize(() => { this.isRefreshingToken = false; // Reset the flag }), ); } else { // Queue requests while a token is being refreshed return this.tokenSubject.pipe( filter((token) => token != null), take(1), switchMap((token) => next(this.addToken(req, token))), ); } }
handleUnauthorized 函數旨在管理 HTTP 請求收到 401 Unauthorized 狀態(指示存取權杖已過期或無效)的場景。此功能可確保應用程式可以刷新令牌並無縫重試失敗的請求。
handleUnauthorized( req: HttpRequest<any>, next: HttpHandlerFn ): Observable<any> { if (!this.isRefreshingToken) { this.isRefreshingToken = true; // Notify all waiting requests that the token is being refreshed this.tokenSubject.next(null); return this.refreshToken().pipe( switchMap((newToken: string) => { if (newToken) { this.tokenSubject.next(newToken); // Retry the original request with the new token return next(this.addToken(req, newToken)); } // If token refresh fails, log out the user this.logout(); return throwError(() => 'Token expired'); }), catchError((error) => { this.logout(); // Log out on error return throwError(() => error); }), finalize(() => { this.isRefreshingToken = false; // Reset the flag }), ); } else { // Queue requests while a token is being refreshed return this.tokenSubject.pipe( filter((token) => token != null), take(1), switchMap((token) => next(this.addToken(req, token))), ); } }
if (!this.isRefreshingToken) { this.isRefreshingToken = true; this.tokenSubject.next(null);
return this.refreshToken(url).pipe( switchMap((newToken: string) => { if (newToken) { this.tokenSubject.next(newToken); return next(this.addToken(req, newToken)); } this.logout(); return throwError(() => 'Token expired'); }),
return this.tokenSubject.pipe( filter((token) => token != null), // Wait for a non-null token take(1), // Only take the first emitted token switchMap((token) => next(this.addToken(req, token))), );
catchError((error) => { this.logout(); return throwError(() => error); }),
將令牌加入到請求
addToken 方法將新令牌附加到傳出請求的標頭中。
finalize(() => { this.isRefreshingToken = false; }),
HttpInterceptor 是實現此工作流程的完美場所。它允許您攔截所有 HTTP 請求並全域處理令牌管理,而無需修改單一服務呼叫。
addToken(request: HttpRequest<any>, token: string): HttpRequest<any> { return request.clone({ setHeaders: { 'X-Token': token, }, }); }
總之,可靠的令牌刷新工作流程可確保 Angular 應用程式中的無縫使用者體驗和安全會話管理。透過有效處理 401 錯誤並管理並發請求,您可以保持可靠性並讓使用者滿意。感謝您的閱讀—請隨時在下面分享您的想法或問題!
以上是Angular 中刷新令牌的詳細內容。更多資訊請關注PHP中文網其他相關文章!