前の記事では、FastAPIブログのユーザー登録システムと基本的なログイン検証ロジックを正常に構築しました。ユーザーはアカウントを作成でき、アプリケーションはユーザー名とパスワードを検証できます。
しかし、現在のログインは一度限りの検証であり、サーバーはユーザーのログイン状態を「覚えて」いません。ページがリフレッシュされるたびに、または新しいページにアクセスするたびに、ユーザーは認証されていないゲストに戻ってしまいます。
この記事では、ミドルウェアを使用してブログの真のユーザーログイン状態管理を実装します。ログインが必要なページや機能を保護し、ユーザーのログイン状態に基づいてインターフェースを動的に更新する方法を学びます。
セッションの設定
FastAPIでセッション管理を処理するために、StarletteのSessionMiddlewareを使用します。StarletteはFastAPIが構築されているASGIフレームワークであり、SessionMiddlewareはセッションを処理するための公式標準ツールです。
まず、itsdangerousライブラリをインストールします。SessionMiddlewareはこれを使用してセッションデータを暗号化署名し、そのセキュリティを確保します。
次に、requirements.txtファイルに追加します。
セッションにRedisを使用する
デフォルトでは、SessionMiddlewareはセッションデータを暗号化し、クライアントサイドのCookieに保存します。このアプローチはシンプルでバックエンドストレージを必要としませんが、Cookieのサイズ制限(通常4KB)という欠点があり、大量のデータ保存には適していません。
より優れたスケーラビリティとセキュリティのために、Redis(高性能インメモリデータベース)を使用してサーバーサイドでセッションを永続化します。これにより、ユーザーがブラウザを閉じたり、サーバーが再起動したりしても、ログイン状態を維持できます。
Redisがない場合は?
LeapcellでRedisインスタンスを作成できます。Leapcellはバックエンドアプリケーションに必要なほとんどのツールを提供します!
インターフェースの「Redisの作成」ボタンをクリックして、新しいRedisインスタンスを作成します。

Redisの詳細ページには、Redisコマンドを直接実行できるオンラインCLIが用意されています。

現時点でRedisサービスが利用できない場合、SessionMiddlewareはデフォルトで署名付きCookieを使用します。このチュートリアルの目的においては、機能に影響はありません。
Redis関連の依存関係をインストールします。
次に、main.pyファイルを開いてSessionMiddlewareをインポートして設定します。
注意: セキュリティのため、secret_keyは複雑なランダムに生成された文字列であるべきです。データベースURLと同様に、ハードコーディングするのではなく、環境変数を通じて管理する必要があります。
設定後、SessionMiddlewareは各リクエストを自動的に処理し、リクエストのCookieからセッションデータを解析してrequest.sessionオブジェクトにアタッチして使用できるようにします。
実際のログインとログアウトルートの実装
次に、実際のログインとログアウトロジックを処理するためにrouters/auth.pyを更新しましょう。
login関数では、ユーザーが正常に検証された後、基本的なユーザー情報を含む辞書をrequest.session["user"]に保存します。SessionMiddlewareは、このセッションデータを自動的に暗号化および署名し、それを含むCookieをブラウザに設定します。ブラウザは、後続のすべてのリクエストにこのCookieを自動的に含めるため、サーバーはユーザーのログイン状態を認識できます。
logout関数では、request.session.clear()を呼び出します。これによりセッションデータがクリアされ、事実上ユーザーはログアウトします。
ルートの保護とUIの更新
ログインメカニズムができたので、最後のステップは、それを使用して「投稿の作成」機能を保護し、ログイン状態に基づいて異なるUI要素を表示することです。
認証依存関係の作成
FastAPIでルートを保護する最もエレガントな方法は、依存関係注入を使用することです。ユーザーがログインしているかどうかを確認する依存関係関数を作成します。
プロジェクトのルートディレクトリで、auth_dependencies.pyという名前の新しいファイルを作成します。
最初の関数login_requiredのロジックはシンプルです。request.sessionにuserが存在しない場合は、ユーザーをログインページにリダイレクトします。存在する場合は、ユーザー情報が返され、ルート関数が直接使用できるようになります。
依存関係の適用
routers/posts.pyを開いて、保護が必要なルートにlogin_required依存関係を適用します。
これで、認証されていないユーザーが/posts/newにアクセスしようとすると、自動的にログインページにリダイレクトされます。
フロントエンドUIの更新
最後に、UIを更新して、ユーザーのログイン状態に基づいて異なるボタンを表示しましょう。get_user_from_session依存関係を使用してユーザー情報を取得し、テンプレートに渡します。
templates/_header.htmlを修正します。
上記のテンプレートが正しく機能するには、ビューにユーザー情報を渡して、ビューをレンダリングするすべてのルートを更新する必要があります。
routers/posts.pyで、ビューをレンダリングするすべてのメソッドを修正します。
同様に、routers/users.pyとrouters/auth.pyのテンプレートレンダリングルートも、user: dict | None = Depends(get_user_from_session)を追加し、userをテンプレートに渡すことで更新する必要があります。
実行とテスト
アプリケーションを再起動します。
http://localhost:8000にアクセスします。右上隅に「Login」と「Register」ボタンが表示されるはずです。
http://localhost:8000/posts/newにアクセスしようとします。ログインページに自動的にリダイレクトされます。
アカウントを登録してログインします。ログインに成功すると、ホームページにリダイレクトされ、右上隅に「Welcome, [Your Username]」、「New Post」、「Logout」ボタンが表示されます。

これで、「New Post」をクリックして新しい記事を作成できます。ログアウトして/posts/newに再度アクセスしようとすると、再びリダイレクトされます。
これで、ブログに完全なユーザー認証システムが追加されました。友達があなたのブログをいじる心配をする必要はもうありません!
Xでフォローする:@LeapcellJP
関連記事: