🔖

Laravelのログイン/ログアウト時のセッションの流れ

に公開

はじめに

Laravelのログイン/ログアウト時のセッションの流れのメモです。

フレームワークの中を少し覗いてLaravelと仲良く(なった気に)なるシリーズです。

シリーズ

諸々

ドキュメントの確認

https://laravel.com/docs/12.x/authentication

用語の整理

Laravelの認証機能

Laravelの認証機能は、その中核を成す「ガード」と「プロバイダー」で構成されています。

ガード = ユーザーの認証方法を定義

ガードは、各リクエストにおけるユーザーの認証方法を定義します。例えば、Laravelには、sessionセッションストレージとCookieを用いて状態を維持するガードが標準装備されています。

プロバイダー = 永続ストレージからユーザーを取得する方法を定義

プロバイダーは、永続ストレージからユーザーを取得する方法を定義します。Laravelは、Eloquentとデータベースクエリビルダーを使用したユーザー取得をサポートしています。ただし、アプリケーションの必要に応じて、追加のプロバイダーを自由に定義できます。

設定ファイル = config/auth.php

アプリケーションの認証設定ファイルは にありますconfig/auth.php。このファイルには、Laravel の認証サービスの動作を微調整するための、よく文書化されたオプションがいくつか含まれています。

認証の仕組み

まず、認証の仕組みを考えてみましょう。Webブラウザを使用する場合、ユーザーはログインフォームからユーザー名とパスワードを入力します。これらの認証情報が正しい場合、アプリケーションは認証されたユーザーに関する情報をユーザーのセッションに保存します。ブラウザに発行されるCookieにはセッションIDが含まれており、アプリケーションへの後続のリクエストでユーザーを正しいセッションに関連付けることができます。セッションCookieを受信すると、アプリケーションはセッションIDに基づいてセッションデータを取得し、認証情報がセッションに保存されていることを確認して、ユーザーを「認証済み」とみなします。

Laravelの組み込みブラウザ認証サービス (上の認証の仕組みとほぼ同じ内容)

Laravelには、組み込みの認証サービスとセッションサービスが含まれており、通常はAuthとSessionファサードを介してアクセスされます。これらの機能は、Webブラウザから開始されたリクエストに対してCookieベースの認証を提供します。これらの機能は、ユーザーの資格情報を検証し、ユーザーを認証するための方法を提供します。さらに、これらのサービスは適切な認証データをユーザーのセッションに自動的に保存し、ユーザーのセッションCookieを発行します。

前提

今回はLaravel breezeをインストールしています。そのため、記事内で登場する以下ファイルはLaravel breezeのファイルです。

その他の以下ファイルはlaravelのファイルです。(ログインやセッションの処理自体はLaravelの機能が使われる)

ログイン時のセッションの流れ

/auth.phpでルーティング(ログインパスは/register)。

https://github.com/laravel/breeze/blob/976ab1e2f68b90eee5a787445ff94033d919be2f/stubs/default/routes/auth.php#L14-L36

Auth/AuthenticatedSessionController.storeメソッドが実行。

https://github.com/laravel/breeze/blob/976ab1e2f68b90eee5a787445ff94033d919be2f/stubs/inertia-common/app/Http/Controllers/Auth/AuthenticatedSessionController.php#L27-L37

Http/Requests/Auth/LoginRequest.phpauthenticateメソッドを実行。

https://github.com/laravel/breeze/blob/976ab1e2f68b90eee5a787445ff94033d919be2f/stubs/api/app/Http/Requests/Auth/LoginRequest.php#L35-L53

1.ガードインスタンスを認証済み状態にする

$user = $this->provider->retrieveByCredentials($credentials)で認証ユーザーを取得。
loginメソッド内の$this->setUser($user)でガードインスタンスにユーザーをセットする。

https://github.com/laravel/framework/blob/54ccc1613c5b66775e3415eaf9f9f88b2d3d1a7f/src/Illuminate/Auth/SessionGuard.php#L402-L436

https://github.com/laravel/framework/blob/54ccc1613c5b66775e3415eaf9f9f88b2d3d1a7f/src/Illuminate/Auth/SessionGuard.php#L540-L566

2.新規のセッションのレコードを作成する

loginメソッド内の$this->updateSession()で、セッションインスタンスの$this->attributes['login_xxx']ログインユーザーのIDを追加

$this->session->migrate(true)migrateメソッドの引数がtrueなので、まずはDBから既存のセッションレコードを削除し、そのあとでセッションIDを再生成しセッションインスタンスの$this->idにセット(セキュリティ対策)

さらに$this->existsプロパティをfalseに更新。(レスポンスが返る前にのミドルウェアでの保存処理する前に、更新か新規追加かの判定でも使われる)

https://github.com/laravel/framework/blob/54ccc1613c5b66775e3415eaf9f9f88b2d3d1a7f/src/Illuminate/Auth/SessionGuard.php#L568-L579

https://github.com/laravel/framework/blob/c7a87ae20172593f7dd498d9b7779b56e051fa82/src/Illuminate/Session/Store.php#L599-L616

(3.セッションID再発行)

すでにセッションIDは新規発行済みですが、Controller側の$request->session()->regenerate()メソッドでもmigrateメソッドを呼んでいるので再度(2度目)セッションIDを新規発行している?

https://github.com/laravel/framework/blob/c7a87ae20172593f7dd498d9b7779b56e051fa82/src/Illuminate/Session/Store.php#L586-L597

ログアウト時のセッションの流れ

app/Http/Controllers/Auth/AuthenticatedSessionController.phpコントローラーのdestroyアクションで実行されます。

https://github.com/laravel/breeze/blob/976ab1e2f68b90eee5a787445ff94033d919be2f/stubs/inertia-common/app/Http/Controllers/Auth/AuthenticatedSessionController.php#L39-L51

1.ガードインスタンスを認証済みではない状態にする

$this->user = null;でnullにする

https://github.com/laravel/framework/blob/54ccc1613c5b66775e3415eaf9f9f88b2d3d1a7f/src/Illuminate/Auth/SessionGuard.php#L618-L644

2.対象のセッションのレコードを削除する

$this->migrate(true);migratetrueを指定しているのでmigrateメソッド内で既存のセッションのレコードを削除しつつ、セッションをIDを再発行している。

https://github.com/laravel/framework/blob/c7a87ae20172593f7dd498d9b7779b56e051fa82/src/Illuminate/Session/Store.php#L574-L584

シリーズ

Discussion