タイトル: ログインの必須化
SEOタイトル: Laravel 認証必須化 (auth Middleware) 完全ガイド|Web / API / Sanctum 統合
| この記事の要点 |
|
Laravel の認証システム概要
Laravel は Guard (認証方式) と Provider (ユーザー取得元) を組み合わせて認証を構成します。設定は config/auth.php。デフォルトは Web Guard (Session ベース) + Eloquent User モデル。
// config/auth.php (抜粋)
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => ['driver' => 'session', 'provider' => 'users'],
'api' => ['driver' => 'token', 'provider' => 'users'], // 旧 token
// Sanctum 利用時は別途設定
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
],
パターン 1: ルート単位の auth Middleware
もっともシンプルで頻出するパターン。routes/web.php でルートに auth ミドルウェアを付与します。
// routes/web.php
use Illuminate\Support\Facades\Route;
// 公開ページ (ログイン不要)
Route::get('/', [HomeController::class, 'index']);
Route::get('/about', fn () => view('about'));
// ログイン必須エリア
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
Route::put('/profile', [ProfileController::class, 'update']);
Route::post('/logout', [AuthController::class, 'logout']);
});
// 認証 + 検証済メール必須
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/billing', [BillingController::class, 'index']);
});
// 認証 + 管理者ロールのみ
Route::middleware(['auth', 'role:admin'])->group(function () {
Route::get('/admin', [AdminController::class, 'index']);
});
パターン 2: Controller コンストラクタで一括
1 つの Controller のほぼ全アクションがログイン必須なら、コンストラクタで指定が楽です。
namespace App\Http\Controllers;
class ArticleController extends Controller
{
public function __construct()
{
// 全アクションに auth を適用
$this->middleware('auth');
// 例外: 一覧と詳細だけは公開
$this->middleware('auth')->except(['index', 'show']);
// または特定アクションのみ
$this->middleware('auth')->only(['create', 'store', 'update', 'destroy']);
}
}
Laravel 11+ では Controller のコンストラクタ Middleware が削除され、ルート側で指定するスタイルに統一されました。バージョンに応じて使い分け。
パターン 3: Laravel 11+ 推奨スタイル
// Laravel 11+ では HasMiddleware インターフェース
namespace App\Http\Controllers;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
class ArticleController extends Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
'auth', // 全アクション
new Middleware('auth', except: ['index', 'show']), // 一部除外
new Middleware(['auth', 'verified'], only: ['edit', 'update']),
];
}
public function index() { /* 公開 */ }
public function show($id) { /* 公開 */ }
public function edit($id) { /* 認証 + 検証済 */ }
}
主要な認証 Middleware
| Middleware | 役割 | 未認証時 |
|---|---|---|
auth | デフォルト Guard で認証必須 | login ルートへリダイレクト |
auth:web | web Guard を明示 | 同上 |
auth:api | api Guard | 401 JSON |
auth:sanctum | Sanctum (SPA + API + Mobile) | 401 JSON or リダイレクト |
auth.basic | HTTP Basic 認証 | 401 + WWW-Authenticate |
auth.session | セッションがあれば認証 | — |
guest | 未ログイン専用 (ログイン画面など) | ホームへリダイレクト |
verified | メール検証済必須 | verification 画面へ |
password.confirm | 直近で再認証必須 | パスワード再確認画面 |
未認証時のリダイレクト先カスタマイズ
// Laravel 10 以前: app/Http/Middleware/Authenticate.php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
protected function redirectTo(Request $request): ?string
{
// API リクエストは null を返して 401 を発生させる
if ($request->expectsJson()) {
return null;
}
// ブラウザはログイン画面へ
return route('login');
}
}// Laravel 11+: bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
->withRouting(...)
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo(fn () => route('login'));
$middleware->redirectUsersTo('/dashboard');
})
->create();
Blade での出し分け
@auth
{{-- ログイン中だけ表示 --}}
こんにちは、{{ Auth::user()->name }} さん
@endauth
@guest
{{-- 未ログイン時だけ表示 --}}
ログイン
新規登録
@endguest
@auth('admin')
{{-- 別 Guard で判定 --}}
管理画面
@endauth
Sanctum での API 認証
SPA / モバイル / API のどれを書いていても Sanctum 1 つで網羅できるのが現代の Laravel スタンダードです。
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', fn (Request $r) => $r->user());
Route::apiResource('articles', ArticleController::class);
});
// トークン発行 (モバイル / 外部システム)
$user = User::find(1);
$token = $user->createToken('mobile-app')->plainTextToken;
// → ヘッダ: Authorization: Bearer 1|abc...
// User モデル
class User extends Authenticatable
{
use HasApiTokens; // ← Sanctum 必須トレイト
}
スターターキットを使う
ログイン画面・登録画面・パスワードリセットを自分で書く必要はありません。Laravel 公式のスキャフォールドを使いましょう。
| キット | 特徴 | 用途 |
|---|---|---|
| Breeze | ★ 最小構成 (Blade / Vue / React / API) | シンプル CRUD アプリ |
| Jetstream | Teams / 2FA / API トークン / Profile 管理 | SaaS |
| Fortify | UI 無しのバックエンドのみ | 独自フロント / Inertia 系 |
# Breeze (Blade 版) の例
composer require laravel/breeze --dev
php artisan breeze:install blade
npm install && npm run dev
php artisan migrate
# /login /register /password/reset /verify-email
# ルートが自動生成 + UI 完成
パスワード再確認
支払い情報変更や退会などセンシティブな操作には、ログイン済でも再度パスワード確認を求めます。
Route::middleware(['auth', 'password.confirm'])->group(function () {
Route::delete('/account', [AccountController::class, 'destroy']);
Route::post('/billing/card', [BillingController::class, 'updateCard']);
});
// 確認後の有効期限 (秒) は config/auth.php
'password_timeout' => 10800, // 既定 3 時間
API リクエストへの 401 JSON 返却
SPA / モバイルからの API リクエストは HTML へリダイレクトされても困ります。Accept: application/json ヘッダ付きなら自動で 401 JSON が返ります。
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"message": "Unauthenticated."
}
テスト
use App\Models\User;
it('未ログインユーザーはダッシュボードからリダイレクトされる', function () {
$this->get('/dashboard')->assertRedirect('/login');
});
it('ログイン済ならダッシュボードが見える', function () {
$user = User::factory()->create();
$this->actingAs($user)
->get('/dashboard')
->assertOk();
});
it('API は 401 JSON を返す', function () {
$this->getJson('/api/user')->assertStatus(401);
});
FAQ
Q: ログイン後に元のページに戻したい
A: auth Middleware は未認証時に url()->previous() をセッションに保存し、ログイン後 redirect()->intended('/default') で復元します。標準でこの動作が含まれているはず。
Q: 一部の URL だけログインを免除したい
A: ルートを別グループに分け、Route::middleware('auth')->group(...) の外に置きます。Controller 単位なら except 引数で指定。
Q: 複数の認証 (顧客 / 管理者) を使い分けたい
A: config/auth.php に複数 Guard と Provider を定義し、auth:admin のように Guard 名付きで Middleware 指定します。
Q: ログインしているのに毎回ログイン画面に戻される
A: セッションドライバの設定ミスが多い。SESSION_DRIVER=file なら storage/framework/sessions の権限、cookie なら SESSION_DOMAIN 設定、HTTPS なら SESSION_SECURE_COOKIE=true を確認。
Q: API でログイン状態をフロントに通知したい
A: SPA + Sanctum の Cookie 認証なら /api/user を叩いて 200 ならログイン中、401 なら未ログインと判定。CSRF は /sanctum/csrf-cookie 先取りが必要。