ホームページ > ウェブフロントエンド > jsチュートリアル > Angularのリフレッシュトークン

Angularのリフレッシュトークン

Patricia Arquette
リリース: 2024-12-31 20:10:13
オリジナル
505 人が閲覧しました

継続的にログインせずにユーザー セッションを維持することが、スムーズな Web エクスペリエンスの鍵となります。このブログでは、Angular でトークン更新ワークフローを実装し、401 エラーを処理し、同時リクエストを効果的に管理する方法を説明します。


リフレッシュ トークン ワークフローとは何ですか?

認証システムでは、セキュリティ リスクを最小限に抑えるためにアクセス トークンの有効期間が短くされています。アクセス トークンの有効期限が切れると、リフレッシュ トークンにより、アプリケーションはユーザーが再度ログインすることなく、サーバーに新しいアクセス トークンをリクエストできるようになります。


Angular の実装

Angular の HttpInterceptor を使用してリフレッシュ トークン メカニズムを実装します。目標は、不正なリクエスト (401 エラー) を傍受し、元のリクエストを再試行する前にトークンを更新することです。


完全なワークフロー

  • リクエストインターセプト:
    インターセプターが 401 Unauthorized 応答を検出しました。

  • トークンの更新:
    トークンの有効期限が切れた場合、refreshToken は新しいトークンを取得します。

  • 再試行リクエスト:
    元のリクエストは新しいトークンを使用して再試行されます。

  • キュー管理:
    トークンが更新されると、保留中のリクエストが処理されます。

Refresh Token in Angular


コードの概要

  1. トークンリフレッシュロジック handleUnauthorized メソッドは、トークンの有効期限が切れたためにリクエストが失敗した場合に、トークンのリフレッシュを処理します。
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 ステータスを受け取るシナリオを管理するように設計されています。この関数により、アプリケーションはトークンを更新し、失敗したリクエストをシームレスに再試行できるようになります。

  1. 複数の更新リクエストを防止する この関数は isRefreshingToken フラグを使用して、一度に 1 つのトークン更新リクエストのみが行われるようにします。トークンがすでに更新されている場合、後続のリクエストは新しいトークンが使用可能になるまでキューに入れられます。
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))),
    );
  }
}
ログイン後にコピー
ログイン後にコピー
  1. トークンを更新する 進行中のリフレッシュ要求がない場合は、refreshToken メソッドを使用してトークンのリフレッシュを開始します。新しいトークンを受信したら:
  • tokenSubject に保存されます。
  • 元のリクエストは更新されたトークンを使用して再試行されます。
if (!this.isRefreshingToken) {
  this.isRefreshingToken = true;
  this.tokenSubject.next(null);

ログイン後にコピー
  1. 同時リクエストの処理 トークンの更新がすでに進行中の場合、関数は後続のリクエストをキューに入れます。これらのリクエストは、tokenSubject が新しいトークンを発行するまで待ってから続行します。
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');
  }),

ログイン後にコピー
  1. エラー処理 トークンの更新が失敗するか、例外がスローされる場合:
  • ユーザーはログアウトしました。
  • 呼び出し元にエラーが返されます。
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))),
);
ログイン後にコピー
  1. クリーンアップ Finalize オペレーターは、isRefreshingToken フラグがリセットされることを保証し、後続のリフレッシュ要求を許可します。
catchError((error) => {
  this.logout();
  return throwError(() => error);
}),

ログイン後にコピー

リクエストへのトークンの追加
addToken メソッドは、送信リクエストのヘッダーに新しいトークンを追加します。

finalize(() => {
  this.isRefreshingToken = false;
}),
ログイン後にコピー

Angular HTTP インターセプターでの使用

HttpInterceptor は、このワークフローを実装するのに最適な場所です。これにより、個々のサービス呼び出しを変更することなく、すべての HTTP リクエストをインターセプトし、トークン管理をグローバルに処理できるようになります。

addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
  return request.clone({
    setHeaders: {
      'X-Token': token,
    },
  });
}
ログイン後にコピー

要約すると、堅牢なトークン更新ワークフローにより、Angular アプリケーションでのシームレスなユーザー エクスペリエンスと安全なセッション管理が保証されます。 401 エラーを効果的に処理し、同時リクエストを管理することで、信頼性を維持し、ユーザーを満足させることができます。お読みいただきありがとうございます。ご意見やご質問をお気軽に下記までお寄せください。

以上がAngularのリフレッシュトークンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート