はじめに
個人開発でマルチログインを実装した後に挙動を確認してみるとsessionが上手く制御できていなかったので解決策を5ステップにまとめて忘備録として残します。
拡張性についても意識して調整を行ったので似たような実装を行なっている方達に参考にしていただけますと幸いです。
前提条件
①ローカル環境上でdocker-composeにて以下の構成になるようにコンテナを作成しています。
言語 php
RDBMS mysql
webサーバーソフトウェア nginx
メールサーバーあり
redisあり
※今回の投稿にて、各ソフトウェアのバージョンは無関係と認識しているので割愛します。
②認証機能についてはLaravel/Breezeを使用しており、Laravel/permissionも導入済みです。
③マルチログイン機能についても実装済みの状態です。
発生した現象と仮説
以前、こちらの記事でマルチログイン機能を実装した際にAdminとCustomerでアカウントテーブルを分離してログイン機能を実装したがsessionの情報を確認した所.....
①ID1のAdminでログインを実施し、sessionsテーブルにレコードが生成されている事を確認
②ID1のAdminでログアウトを実施し、①によって生成されたレコードの内容が更新
③ID1のCustomerでログインを実施し、sessionsテーブルにレコードが生成されるかと思いきや、①によって生成されたレコードの内容が更新
→IDが同一の & 同一のsessionsテーブルで管理している関係で正しいsessionsレコードの発行~更新がされていないと推測
対応内容
各guard用のsessionsテーブルを作成してmiddlewareの処理で制御されるように調整
具体的な対応内容
1.以下のMigrationファイルの作成を行なって、テーブルの作成を実施する
admin_sessions
customer_sessions
// create()の第一引数は上記の項目の通りに書き換えてください
Schema::create('xxxxxxxxx_sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
public function down(): void
{
Schema::dropIfExists('xxxxxxxxx_sessions');
}
2.以下のコマンドを実行して①のtableの作成を実施する
php artisan migrate
3.以下のコマンドでmiddlewareファイルの作成を行う
php artisan make:middleware SetSessionTablePerGuard
※Class名については一目で分かるような任意の名前であれば問題ないです。
4.作成したMiddlewareのhandleを以下の通りに編集
if ($request->is('admin/*')) {
Config::set('session.table', 'admin_sessions');
}
if ($request->is('customer/*')) {
Config::set('session.table', 'customer_sessions');
}
return $next($request);
}
→内容としてはシンプルでurlがadmin関連の場合はadmin_sessionsテーブルを参照して、customer関連の場合はcustomer_sessionsテーブルを参照するといったロジック
5.app.phpへの設定
bootstrap/app.phpの中に作成したクラスを記載します
$middleware->alias([
'set.session.table' => \App\Http\Middleware\SetSessionTablePerGuard::class,
]);
→StartSession が先に動くと、config('session.table') はすでに読み込まれておりそちらを優先してtableに情報が書き込まれるので、web.phpではなくprepend()を使用して先行して動作するように制御します。
まとめ
上記の通りに実装する事でsessionを対象のテーブルで制御できるようになるかと思います。
マルチログインの実装方法については是非以下の記事を参考にしてみて下さい。