趣旨 & 前置き
Laravel5.6のコードを読んでいきます。
Laravel標準の認証では、認証済み(ログイン済み)の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトします。
認証について解説するページは多いですが、このあたりの動きを解説しているページってみたことないので、書いてみようと思いました。
確認する環境はHomesteadでLaravelをインストールし、
php artisan make:auth
php artisan migrate
だけやった状態だと思います(うろ覚え)
Let's コードリーディング!
ログインしている場合にログイン後のトップページにリダイレクトする処理はApp\Http\Middleware\RedirectIfAuthenticatedクラスに書かれています。
RedirectIfAuthenticatedクラス
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
認証しているかチェックして、認証していたら/homeにリダイレクトしています。
これが「認証済み(ログイン済み)の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトする」処理です。(guardなどの細かい説明についてはここではしません。)
さて、問題はこのRedirectIfAuthenticatedクラスがどのように呼び出されているかです。
ネームスペースでわかる通り、RedirectIfAuthenticatedクラスはミドルウェアです。どこかでこのミドルウェアを指定する箇所があるはずです。探してみましょう。
Kernelクラス
開発中のアプリケーションで利用されるミドルウェアはApp\Http\Kernelクラスに記述します。
該当部分を抜粋します。
protected $routeMiddleware = [
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];
RedirectIfAuthenticatedクラスはguestという名前で登録されているようです。
ルーティングの確認
guestという名前のミドルウェアがどのルーティングで利用されているのかを確認するために、ルーティングを確認してみましょう。
まず、routes/web.phpをみてみます。
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
これだとなんだかよくわかりませんね。
なので以下のコマンドでルーティングの確認をしてみましょう。
php artisan route:list
ルーティングの一覧が表示されるかと思います。
今回関連する部分を抜粋します。
Domain | Method | URI | Name | Action | Middleware |
---|---|---|---|---|---|
GET/HEAD | home | home | App\Http\Controllers\HomeController@index | web | |
GET/HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest | |
POST | login | App\Http\Controllers\Auth\LoginController@login | web,guest | ||
POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web | |
POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest | |
GET/HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest | |
POST | password/reset | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest | ||
GET/HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest | |
GET/HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest | |
POST | register | App\Http\Controllers\Auth\RegisterController@register | web,guest |
guestミドルウェアが利用されていますね。ミドルウェアが利用されているミドルウェアの指定はControllerのコンストラクタでも可能ですから、LoginControllerクラス / RegisterControllerクラス/ResetPasswordControllerクラス/ForgotPasswordControllerクラスを覗いてみましょう。
LoginControllerクラス / RegisterControllerクラス / ResetPasswordControllerクラス / ForgotPasswordControllerクラス
App\Http\Controllers\Auth\LoginControllerクラスのコンストラクタをみてましょう。
public function __construct()
{
$this->middleware('guest')->except('logout');
}
App\Http\Controllers\Auth\RegisterControllerクラス、App\Http\Controllers\Auth\ResetPasswordControllerクラス、App\Http\Controllers\Auth\ForgotPasswordControllerクラスのコンストラクタも同じように見てみます。
public function __construct()
{
$this->middleware('guest');
}
ありました。guestミドルウェア = RedirectIfAuthenticatedクラスを指定しています。これで「認証済み(ログイン済み)の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトする」仕組みが理解できたと思います。
webミドルウェア
ルーティングの一覧のところにwebというミドルウェアグループも指定されていましたが、これについてもどこで指定されているのか確認してみましょう。
webミドルウェアグループはKernelクラスに以下のように記述されています。
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,
]
];
webミドルウェアグループがどこで指定されているのかは、実はドキュメントにちゃんと書いてあります。このへんです。(突然の大雑把)
Tip!! RouteServiceProviderにより、routes/web.phpファイルでは、webミドルウェアグループが自動的に適用されます。
そう、App\Providers\RouteServiceProviderクラスで指定されているのです。
RouteServiceProviderクラス
例によってRouteServiceProviderクラスの該当箇所を抜粋してみます。
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
ここでwebミドルウェアグループを指定していますね!
このコードが示す通り、routes/web.phpに記述されたルーティングは基本的にwebミドルウェアが利用されるようです。
終わりに
間違ってたら指摘オナシャス。