継続的にログインせずにユーザー セッションを維持することが、スムーズな Web エクスペリエンスの鍵となります。このブログでは、Angular でトークン更新ワークフローを実装し、401 エラーを処理し、同時リクエストを効果的に管理する方法を説明します。
認証システムでは、セキュリティ リスクを最小限に抑えるためにアクセス トークンの有効期間が短くされています。アクセス トークンの有効期限が切れると、リフレッシュ トークンにより、アプリケーションはユーザーが再度ログインすることなく、サーバーに新しいアクセス トークンをリクエストできるようになります。
Angular の HttpInterceptor を使用してリフレッシュ トークン メカニズムを実装します。目標は、不正なリクエスト (401 エラー) を傍受し、元のリクエストを再試行する前にトークンを更新することです。
リクエストインターセプト:
インターセプターが 401 Unauthorized 応答を検出しました。
トークンの更新:
トークンの有効期限が切れた場合、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 中国語 Web サイトの他の関連記事を参照してください。