在不持续登录的情况下维持用户会话是流畅网络体验的关键。在这篇博客中,我将向您展示如何在 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中文网其他相关文章!