タイトル: ルートの認証化
SEOタイトル: Laravel ルート認証化完全ガイド — middleware と Gate
| この記事の要点 |
|
基本: auth middleware
ログイン必須にしたいルートに auth middleware を付けます:
// routes/web.php
use App\Http\Controllers\DashboardController;
// 単一ルートに付与
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware('auth')
->name('dashboard');
// グループに一括付与
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'show']);
Route::put('/profile', [ProfileController::class, 'update']);
Route::delete('/account', [AccountController::class, 'destroy']);
});
// プレフィックス + 名前空間 + middleware
Route::middleware(['auth', 'verified'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/users', [Admin\UserController::class, 'index'])->name('users.index');
});
未ログインで /dashboard にアクセスすると /login へリダイレクトされます。
認証 guard の指定
| middleware | 用途 | 備考 |
|---|---|---|
auth | Web セッション認証 | デフォルト guard |
auth:sanctum | SPA / API トークン | Laravel 推奨 |
auth:api | Passport API トークン (旧) | Passport 利用時 |
auth:admin | カスタム guard (admin) | config/auth.php で定義 |
auth.basic | HTTP Basic 認証 | クイック保護用 |
verified | メール認証済のみ | auth と併用 |
guest | 未ログインのみ | login / register 画面用 |
password.confirm | パスワード再確認 | センシティブ操作前 |
API ルート (Sanctum)
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', fn(Request $r) => $r->user());
Route::apiResource('posts', PostController::class);
});
// 公開API + 認証必須API を併存
Route::get('/public/posts', [PublicPostController::class, 'index']);
Route::middleware('auth:sanctum')->get('/private/posts', [PrivatePostController::class, 'index']);
認可: can middleware
「自分の投稿しか編集できない」等の所有者チェックは Policy + can middleware:
// routes/web.php
Route::put('/posts/{post}', [PostController::class, 'update'])
->middleware(['auth', 'can:update,post']);
// app/Policies/PostPolicy.php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
// app/Providers/AuthServiceProvider.php
protected $policies = [
Post::class => PostPolicy::class,
];
Form Request での authorize()
// app/Http/Requests/PostUpdateRequest.php
class PostUpdateRequest extends FormRequest
{
public function authorize(): bool
{
// route("post") が暗黙バインドの Post モデル
return $this->user()->id === $this->route('post')->user_id;
}
public function rules(): array
{
return ['title' => 'required|max:100'];
}
}
authorize() が false を返すと 403 Forbidden。
ゲスト専用ルート
ログイン済ユーザーが /login にアクセスしたら /dashboard へリダイレクトしたい:
// routes/web.php
Route::middleware('guest')->group(function () {
Route::get('/login', [LoginController::class, 'show'])->name('login');
Route::post('/login', [LoginController::class, 'store']);
Route::get('/register', [RegisterController::class, 'show'])->name('register');
Route::post('/register', [RegisterController::class, 'store']);
});
// app/Http/Middleware/RedirectIfAuthenticated.php
public function handle($request, Closure $next, ...$guards)
{
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
}
return $next($request);
}
ログイン後リダイレクト先のカスタマイズ
// app/Http/Middleware/Authenticate.php
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
// LoginController で 認証成功後のリダイレクト
protected $redirectTo = '/dashboard';
// または method override
protected function redirectTo()
{
return Auth::user()->isAdmin
? '/admin'
: '/dashboard';
}
SPA + Sanctum パターン
// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000')),
// routes/api.php
Route::middleware(['auth:sanctum'])->group(function () {
Route::get('/me', fn(Request $r) => $r->user());
});// フロント (Vue / React) 側
// CSRF Cookie を取得
await axios.get('/sanctum/csrf-cookie');
// ログイン
await axios.post('/login', { email, password });
// 認証必須 API
const res = await axios.get('/api/me');
middleware の組合せ実例
// 管理画面: 認証 + メール認証 + 管理者ロール + パスワード再確認
Route::middleware([
'auth',
'verified',
'role:admin',
'password.confirm:120', // 120分以内に再確認
])->prefix('admin')->group(function () {
Route::get('/users/{user}/destroy', [Admin\UserController::class, 'destroy'])
->middleware('can:delete,user');
});
FAQ
Q: middleware を全ルートに掛けたい
A: app/Http/Kernel.php の $middleware (グローバル) または $middlewareGroups (web/api) に登録。
Q: 認証エラー時に JSON を返したい
A: Authenticate::redirectTo() 内で $request->expectsJson() を判定。null を返すと自動で 401 JSON。
Q: 複数 guard を OR で組合せたい
A: auth:web,admin のようにカンマ区切り。どちらかに通れば OK。
Q: middleware の順番は重要?
A: 重要。auth → verified → can の順が一般的。auth 前に can を置くと user が null でエラー。