マルチ認証と言っても、複数のステップでユーザーを認証するわけでもなく、ちょっとピンと来ないですね。
例えばECシステムにおいて、ユーザー画面での会員ログインと、管理画面での管理者のログインがそれぞれ別に必要とします。どちらもログインはEメールとは限らないし、片方でログインしたらもう片方でも認証となるとも限りません。つまり、ログインするユーザーの種類や場所が複数必要となる状況が多々あります。それに対応する機能が、マルチ認証です。
Laravelの5.1までは、マルチ認証は対応していなく、以下のようなパッケージをインストールして使用していました。
Laravel4.2対応のLaravel Multi Auth
Laravel5.1対応のMultiAuth for Laravel 5.1
しかし、5.2からはLaravelの基本仕様となっています。さすが、Taylorくん!
今回はこの機能を見てみましょう。
まず、デフォルトでインストールされるconfig/auth.php
の中身の解析。
Laravel 5.1では、
return [ /* デフォルトの認証ドライバー */ 'driver' => 'eloquent', /* 認証に使用されるモデル */ 'model' => App\User::class, /* 認証に使用されるDBテーブル。ここでは、dirverがdatabaseでないので関係ない */ 'table' => 'users', /* パスワードリセットの設定 */ 'password' => [ 'email' => 'emails.password', // resources/views/emails/passwordをリンク送信メールのテンプレートとする 'table' => 'password_resets', // パスワードリセットのトークンの情報を保存するDBテーブル 'expire' => 60, // トークンは60分で期限切れ ], ];
これがLaravel5.2では、
return [ /* 認証のデフォルト設定 */ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], /* 認証のガードを定義 */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], ], /* 認証のプロバイダー */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* パスワードリセットの設定 */ 'passwords' => [ 'users' => [ 'provider' => 'users', 'email' => 'auth.emails.password', 'table' => 'password_resets', 'expire' => 60, ], ], ];
となりました。違いは、guards
とproviders
の導入です。
ちょっとこれではわかりにくいので、先の例を使って、ECサイトを想像してもらって、ショッピングをするユーザ画面と、サイトを管理する管理者画面があり、どちらもログインで認証が必要と仮定しましょう。ユーザー画面では買い物かごをチェックアウトするには、会員のログインが必要とします。
となると必要な設定は以下にようになります。
return [ /* 認証のデフォルト設定 */ 'defaults' => [ 'guard' => 'users', 'passwords' => 'users', ], /* 認証のガードを定義 */ 'guards' => [ 'users' => [ 'driver' => 'session', 'provider' => 'users_provider', ], 'admin_users' => [ 'driver' => 'session', 'provider' => 'admin_users_provider', ], ], /* 認証のプロバイダー */ 'providers' => [ 'users_provider' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'admin_users_provider' => [ 'driver' => 'eloquent', 'model' => App\AdminUser::class, ], ], /* パスワードリセットの設定 */ 'passwords' => [ 'users' => [ 'provider' => 'users_provider', 'email' => 'auth.emails.password', 'table' => 'password_resets', 'expire' => 60, ], ], ];
ガードには、会員ログインのためのusers
と、管理者ログインのためのadmin_users
の2つを定義します。どちらもセッションを使って、ログイン後の画面をプロテクトします。また、それらのプロバイダーで定義されているように、会員のUsers
と管理者のAdminUsers
のエロクエントモデルが認証のための情報提供元となります。
guards
とproviders
の概念を導入することにより、今までの1つだけの認証のメカニズムを複数としたわけです。
さて、次はこの設定の使用です。このファイル以外で使用するのは、ガード名だけですから簡単です。
ガードを指定する場所はプログラムの中でいくつかありますが、以下のようにapp/Http/routes.php
で使用されるのが一番明確と思います。
例えば、ユーザー画面では、
Route::group(['middleware' => 'guest:users'], function() { Route::get('login', 'user\AuthController@getLogin'); Route::post('login', 'user\AuthController@postLogin'); Route::get('signup', 'user\SignupController@getSignup'); Route::post('signup', 'user\SignupController@postSignup'); Route::get('password/email', 'user\PasswordController@getEmail'); Route::post('password/email', 'user\PasswordController@postEmail'); Route::get('password/reset/{token}', 'user\PasswordController@getReset'); Route::post('password/reset', 'user\PasswordController@postReset'); }); Route:: group(['prefix' => 'member', 'middleware' => 'auth:users'], function() { Route::get('index', 'user\MemberController@getIndex'); Route::get('password', 'user\MemberController@getPassword'); Route::post('password', 'user\MemberController@postPassword'); Route::get('profile', 'user\MemberController@getProfile'); Route::post('profile', 'user\MemberController@postProfile'); Route::get('logout', 'user\AuthController@getLogout'); });
以前、ユーザー認証(4)認証でページを保護で説明したように、
ミドルウェアとして、guest
とauth
が使われます。しかし、前回と違って、guest:users
のようにガード名を指定することが必要です。指定がないなら、auth.php
のデフォルトのセクションで指定したガードが自動的に使われます。
ちなみに、管理者側では、
Route::group(['prefix' => 'admin', 'middleware' => 'guest:admin_users'], function() { Route::get('login', 'admin\AuthController@getLogin'); Route::post('login', 'admin\AuthController@postLogin'); }); Route:: group(['prefix' => 'admin', 'middleware' => 'auth:admin_users'], function() { Route::get('logout', 'admin\AuthController@getLogout'); Route::get('index', 'admin\HomeController@getIndex')->name('admin.home'); ..
こんな感じです。
AuthController
は、ユーザ画面と管理画面では、前回紹介した自動作成使われるもののコピーを編集する必用あります。
ユーザ画面では、
... class AuthController extends BaseController { protected $guard = 'users'; protected $redirectTo = 'user/member/index'; // ログイン後のリダイレクト先 protected $redirectAfterLogout = 'user/login'; // ログアウト後のリダイレクト先 protected $username = 'email'; // ログインとなるDBの項目名 protected $maxLoginAttempts = 5; // ログインスロットルとなるまで最高のログイン失敗回数 protected $lockoutTime = 60; // ログインスロットルとなってからの待ち秒数 use AuthenticatesAndRegistersUsers, ThrottlesLogins; public function showLoginForm() { return view('user.login'); //テンプレートの場所を変える } ..
管理画面では、
... class AuthController extends BaseController { protected $guard = 'admin_users'; protected $redirectTo = 'admin/index'; // ログイン後のリダイレクト先 protected $redirectAfterLogout = 'admin/login'; // ログアウト後のリダイレクト先 protected $username = 'login'; // ログインとなるDBの項目名 protected $maxLoginAttempts = 5; // ログインスロットルとなるまで最高のログイン失敗回数 protected $lockoutTime = 60; // ログインスロットルとなってからの待ち秒数 use AuthenticatesUsers, ThrottlesLogins; public function showLoginForm() { $form = new \stdClass(); $form->login = Form::text('login', '', ['size' => 20, 'maxlength' => 20, 'class' => 'en', 'autofocus' => 'autofocus']); $form->password = Form::password('password', ['size' => 40, 'maxlength' => 20, 'class' => 'en']); return view('admin.login')->with(compact('form')); //テンプレートの場所を変える } ..
となります。認証が2つとなると、テンプレートなどいろいろな指定が必要となることに注意してください。上の例では、会員のログインは、emailですが、管理者のログインは、emailでなくてもよい文字列という仮定です。
最後に、ログイン後にログインしたユーザーの情報がほしいときは、今まで、
Auth::user()
でしたが、マルチ認証となると、
Auth::guard('users')->user()
Auth::guard('admin_users')->user()
と明確にガード名を指定する必用があります。
メルマガ購読の申し込みはこちらから。