はじめに
- 認証と権限管理は実案件で必ず必要になる
- Fortifyを使ったマルチ認証は情報が少ない
- 本記事のゴール:
「一般ユーザー」「管理者」「店舗代表者」を完全に分離したログイン/ログアウト/リダイレクトを実現
環境と前提
- Laravel 10 / Fortify
- Docker(任意)
- PHP 8.2
- 認証対象:
- 一般ユーザー(usersテーブル)
- 管理者(adminsテーブル)
- 店舗代表者(ownersテーブル)
Fortify導入
- composer require laravel/fortify
- php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
- Config/fortify.php 設定
認証ガードの追加
- Config/auth.php にガード・プロバイダを定義
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'owner' => [
'driver' => 'session',
'provider' => 'owners',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
'owners' => [
'driver' => 'eloquent',
'model' => App\Models\Owner::class,
],
],
ルーティングの分離
// routes/web.php
// 一般ユーザー
Route::middleware('guest:web')->group(function () {
Route::get('/login', [UserAuthenticatedSessionController::class, 'create']);
Route::post('/login', [UserAuthenticatedSessionController::class, 'store']);
});
// 管理者
Route::prefix('admin')->middleware('guest:admin')->group(function () {
Route::get('/login', [AdminAuthenticatedSessionController::class, 'create']);
Route::post('/login', [AdminAuthenticatedSessionController::class, 'store']);
});
// 店舗代表者
Route::prefix('owner')->middleware('guest:owner')->group(function () {
Route::get('/login', [OwnerAuthenticatedSessionController::class, 'create']);
Route::post('/login', [OwnerAuthenticatedSessionController::class, 'store']);
});
コントローラの実装
- 例:管理者用
namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminAuthenticatedSessionController extends Controller
{
public function create()
{
return view('admin.auth.login');
}
public function store(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::guard('admin')->attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/admin/dashboard');
}
return back()->withErrors([
'email' => 'ログイン情報が正しくありません。',
]);
}
public function destroy(Request $request)
{
Auth::guard('admin')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/admin/login');
}
}
Fortifyのカスタマイズ
- FortifyServiceProvider で guard を切り替える例を紹介
- それぞれのユーザー種別にカスタムビューを指定
ハマりどころ
- 同じブラウザで別ガード同時ログインするとセッションが衝突する
- RedirectIfAuthenticated を書き換えないとリダイレクトが混乱する
- middleware(auth:admin) / (auth:owner) の使い分け
まとめ
- Fortifyは柔軟に拡張できる
- 実案件での「利用者/管理者/店舗代表者」の分離に応用可能