タイトル: Middleware内でAuth::check()などを使用する方法
SEOタイトル: Laravel Middleware で Auth を使う完全ガイド
| この記事の要点 |
|
結論: Middleware で Auth ヘルパーを使うコード
route('login');
}
// ユーザを取得して属性チェック
$user = Auth::user();
if (! $user->is_premium) {
return redirect()->route('upgrade')
->with('error', 'Premium プランが必要です');
}
// 認証 ID をログに
\Log::info('Premium access', ['user_id' => Auth::id()]);
return $next($request);
}
}
Auth Facade と Helper の対応
| Facade | Helper | 意味 |
|---|---|---|
Auth::check() | auth()->check() | 認証済か (bool) |
Auth::user() | auth()->user() | User モデル (or null) |
Auth::id() | auth()->id() | ユーザ ID (int or null) |
Auth::guest() | auth()->guest() | 未認証か |
Auth::guard('api') | auth('api') | ガード指定 |
Auth::logout() | auth()->logout() | ログアウト |
Middleware Group とセッション
Auth::check() はセッションを使うため、StartSession ミドルウェアが先に動いている必要があります。Laravel のデフォルトでは web グループに StartSession / EncryptCookies が含まれていて、api グループには含まれません。
Laravel 10 以前 (Kernel.php)
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class, // ★ これが先に必要
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'premium' => \App\Http\Middleware\EnsurePremiumUser::class, // ★ 登録
];
Laravel 11 (bootstrap/app.php)
Laravel 11 では Kernel.php が廃止され、すべて bootstrap/app.php で設定します:
// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'premium' => \App\Http\Middleware\EnsurePremiumUser::class,
]);
// web グループに独自ミドル追加
$middleware->web(append: [
\App\Http\Middleware\TrackLastActivity::class,
]);
// api グループに Sanctum stateful
$middleware->statefulApi();
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
ルートでの利用
// routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PremiumController;
Route::middleware(['auth', 'premium'])->group(function () {
Route::get('/dashboard', [PremiumController::class, 'index']);
Route::get('/reports', [PremiumController::class, 'reports']);
});
// 単一ルートに付与
Route::get('/profile', [ProfileController::class, 'show'])
->middleware('auth');
API での認証 (Sanctum)
API では Cookie セッションではなく Bearer Token を使うため、Auth::guard('sanctum') を明示します:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class CheckApiToken
{
public function handle(Request $request, Closure $next): Response
{
if (! Auth::guard('sanctum')->check()) {
return response()->json(['error' => 'Unauthenticated'], 401);
}
$user = Auth::guard('sanctum')->user();
$request->setUserResolver(fn () => $user); // 後続で Auth::user() でも取れるように
return $next($request);
}
}
config/auth.php の guards
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [ // 古い形 (passport)
'driver' => 'passport',
'provider' => 'users',
],
'sanctum' => [ // Sanctum 専用
'driver' => 'sanctum',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
],
];
未認証時のリダイレクト先を制御
// 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 経路はリダイレクトせず JSON 401 を返す
if ($request->expectsJson()) {
return null;
}
// 管理画面は別のログインへ
if ($request->is('admin/*')) {
return route('admin.login');
}
return route('login');
}
}
Closure-based Middleware (Laravel 11)
クラスを作らず、ルートに直接クロージャミドルウェアを書く方法:
// routes/web.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Route::get('/admin', function () {
return view('admin.index');
})->middleware(function (Request $request, Closure $next) {
if (! Auth::check() || ! Auth::user()->is_admin) {
abort(403);
}
return $next($request);
});
Middleware で Auth が null になる原因
| 症状 | 原因 | 対処 |
|---|---|---|
Auth::check() が常に false | routes/api.php に置いた | web グループにする or Sanctum guard 指定 |
Auth::user() が null | SubstituteBindings より前で呼んでいる | $middlewareAliases の順序を後ろに |
| セッションが消える | SESSION_DOMAIN ミス | .env の SESSION_DOMAIN を修正 |
| Auth::guard('web')->user() のみ取れる | config/auth.php で defaults.guard が web | guard 明示すれば OK |
FAQ
Q: コンストラクタで Auth::user() が null になる
A: Controller のコンストラクタはセッション初期化前なので null。$this->middleware(function ($request, $next) {...}) パターンで参照するか、メソッド内で呼びます。
Q: API でも CSRF ミドルが効いて 419 になる
A: routes/api.php に置いたか、bootstrap/app.php の statefulApi 設定を見直してください。
Q: Auth::user() の型を Phpstan が User として認識しない
A: /** @var \App\Models\User $user */ で型ヒント追加、または config/auth.php の providers.users.model が正しいか確認。