これでわかるLaravel7.Xのマルチ認証(Multi Auth)の設定方法

Laravel7環境で複数のモデル(User, Employee)を利用したマルチ認証(multi authentification)の設定を行います。本文書のマルチ認証では異なる2つのログイン画面を準備し、1つは一般のユーザ向け(User)でECサイトのようにだれでもユーザ登録を行うことができます。もう一つは従業員向け(Employee)を想定してユーザ向けとは異なりユーザを自由に登録することができません。
本文章では2つ目のモデルをemployeeとしていますが、adminでもstaff、studentでも問題ありません。アプリケーションにあった任意の名前を付けてください。もう一つのモデルはLaravelのデフォルトのuserを利用します。
マルチ認証に必要な設定変更の理由も詳細に説明しているので本文書を読めばマルチ認証だけでなく通常の認証の理解にもつながります。
目次
環境の構築
最初にLaravel、認証、データベースなどの環境構築を行います。composerがインストールされている環境を前提に環境構築を進めていきます。
Laravelプロジェクトの作成
任意のディレクトリでcomposerコマンドを利用してLaravelプロジェクトの作成を行います。laravel newコマンドを利用してプロジェクトの作成を行うこともできます。
作成されたaravel_multi_authに移動してバージョンを確認します。7.9.2で動作確認を行ったことがわります。
ui機能の追加
Laravelではデフォルトでは認証機能を利用することができないので、認証機能の骨組み(scaffolding)が含まれるlaravel/uiをインストールすることで利用できるようになります。


認証機能のインストール
laravel/uiをインストールした認証機能をLaravelに反映させるために以下のコマンドを実行します。ここではvueをフロントエンドのフレームワークに指定していますが、文字列をvueからreactまたはbootstrapに変更するとvue以外のフレームワークに変更することができます。
実行するとweb.phpファイルに認証に関するルーティングの設定を行うAuth:routes()が追加されます。またapp¥Http¥Controllersの下にAuthディレクトリ、resources¥viewsの下にauthディレクトリが作成されます。これらのディレクトリの下にはすべて認証に関するファイルが作成されています。
JavaScriptのインストール
JavaScript関連のライブラリ・パッケージのインストールとビルドを行います。実行後処理完了までに少し時間がかかります。
開発サーバの起動
php artisan serveコマンドを実行して、開発サーバの起動を行います。
認証機能がついているので右上にはLOGINとREGISTERの文字列とリンクがはられます。laravel/uiをインストールしていない場合は右上にリンクが表示されることはありません。

データベースの設定
データベースには簡易的に使用できるSQLiteデータベースを利用します。databaseフォルダの中にdatabase.sqliteファイルを作成します。
.envファイルにはデフォルトではMySQLデータベースの設定が行われているのでSQLiteデータベースの設定に変更します。DB関連のパラメータが複数設定されてますが、DB_CONNECTIONをsqliteに設定して残りのパラメータは削除(DB_XXXXXX)します。DBが先頭につく変数はDB_CONNECTIONのみになります。
DBの設定が完了したら、php artisan migrateコマンドを実行してテーブルの作成を行ってください。
テーブルの作成が完了したらデータベースが問題なく動作しているか確認するためにブラウザからユーザの登録を行いユーザが作成できるか確認を行っておいてください。
マルチ認証の設定
これまでの設定で通常の認証設定は完了しました。ここからEmployeeモデルを作成しマルチ認証の設定を行っていきます。冒頭でも説明しましたがEmployeeというのは任意の名前なのでAdmin等アプリケーションにあった名前に変更してください。
モデルの作成
php artisanコマンドを利用してEmployeeモデルの作成を行います。作成時に-mオプションをつけるとEmployeeマイグレーションファイルも一緒に作成します。
database¥migrationsフォルダに作成されるemployeesのマイグレーションファイルには既存のusersテーブルのマイグレーションファイルの列情報をコピーして貼り付けます。
モデルファイルのEmployee.phpもUser.phpファイルの中身をコピーして貼り付けます。クラス名はEmplyeeなので注意してください。
テーブルの作成
php artisan migrateコマンドを実行してempolyeesテーブルの作成を行います。
ルーティングの追加
デフォルトから存在するUser認証のルーティングはweb.phpファイルのAuth:routesによって登録されます。
Auth:routesメソッドの処理の内容は、Laravel5, 6の時はAuth.phpファイルの中に含まれていましたがLaravel7からはlaravel/uiのパッケージの中に含まれているlaravel¥ui¥src¥AuthRouteMethods.phpファイルの中に記述されています。
Employeeの認証に関するルーティングを追加するためにweb.phpファイルに下記を追加します。
設定したルーティングに関してはphp artisan route:listコマンドで確認することができるので実行します。


prefixにemployeeを付与することで追加したURIのすべてにemployeeがつくことが確認できます。prefixの設定によりUserのログインのパスがloginで、Emplyeeの場合はemplyee/loginと分けることができています。
しかし、NameやActionが同じ名前になっているのでこれらも別に分ける必要があります。そのためルーティングにNamespaceとnameを追加します。

追加後に再度php artisan route:listを実行するとemployeeのルーティングに対応するLoginController.phpファイル等が存在しないためエラーが表示されます。
Controllerファイルの複製
app¥Http¥Controllersの下にEmployeeディレクトリを作成し、app¥Http¥Controllersの下にあるUser用のAuthディレクトリをその下に複製します。
複製したファイルのnamspaceはすべてApp\Http\Controllers\AuthになっているのでApp\Http\Controllers\Employee\AuthとAuthの前にEmployeeを入れて変更を行ってください。
変更後php artisan route:listを実行するとURI、Name, Action列での重複がなくります。



ユーザの登録確認
通常のユーザのユーザ登録のパス/registerですが、Employeeユーザのパスは/employee/registerになっているので、直接ブラウザから/employee/registerにアクセスします。

画面はユーザ登録画面が表示されますがこの画面から登録してもemployeesテーブルにユーザを登録することができません。
原因を探るためにブラウザで表示されている画面のソースを確認します。POSTメソッドの行き先のURLがhttp://127.0.0.1:8000/registerになっています。

これではPOSTメソッドを実行してもPOSTの先が/registerなのでusersテーブルに登録が行われれてしまいます。

登録画面のviewファイルを探す
ユーザ登録画面を表示させているviewファイルがどのファイルか確認するためにEmployee¥Authの下にあるRegisterController.phpファイルを確認します。確認してもviewファイルについての情報は記述されていません。
php artisan route:listを見るとURLの/employee/registerのActionがRegisterController@showRegistrationForm メソッドになっていることがわかります。
showRegistrationFormメソッドはRegisterController.phpではなくその中に記述されているtraitのRegistersUsersに含まれています。
RegisterUsers.phpファイルにshowRegistrationFormメソッドが存在し、auth.registerがviewファイルであることがわかります。
resources¥views¥authの下にあるregister.blade.phpファイルを見るとPOSTのURLがroute(‘register’)となっておりこのregisterはphp artisan route:listで実行した時に確認したName列に対応します。ここをemployee.registerに変更する必要があります。
auth以下のviewファイルの複製
この他のログイン画面についてもbladeファイルの中でルーティングのNameが使用されているためすべてempolyee.XXXに変更を行う必要があります。viewsの下にempolyeeディレクトリを作成し、views¥authをそのままemplyeeの下に複製します。
view¥empolyee¥auth¥register.blade.phpファイルを開いてPOSTメソッドのactionのrouteの中を変更します。
変更してもtraitのRegistersUsersにあるshowRegistrationFormメソッドはview(‘auth.register’)になっているため、view(‘employee.auth.register’)に変更する必要があります。
メソッドの上書き
Employee¥Authの下にあるRegisterController.phpファイルにshowRegistrationFormメソッドを追加し、traitのメソッドを上書きします。
これらの設定が完了してemployeeのユーザ登録画面のURLにアクセスすると/emplyee/registerにPOSTされることが確認できます。

createメソッドの変更
/employee/registerにPOSTメソッドが実行されるとEmployee¥Auth¥RegisterController.phpファイルのcreateメソッドが実行されます。しかしcreateメソッド内のモデルがUserに設定されているのでUserテーブルへの登録になります。これをUserからEmployeeに変更する必要があります。

ここまでの設定が完了すると/employee/registerのユーザ登録画面からユーザの登録を行うとemployeesテーブルにユーザが作成することができます。
テーブルへの接続にはデータベースの管理ソフトウェアのTablePlusがおすすめです。
ユーザ登録を登録することができましたがユーザ登録後に/homeにリダイレクトされます。これはUserのログイン後の初期画面なのでEmployeeでは異なる初期画面にする必要があります。
初期画面へのリダイレクト設定
$redirectTo変数の設定
登録後にリダイレクトされるURLは、RegisterController.phpファイルの$redirectTo変数の設定値で決まります。
RouteServiceProvicer.phpを開いてEMPLOYEE_HOMEを追加します。
RegisterController.phpファイルの$redirectTo変数の値も変更します。
ルーティングの追加
/employee/homeのルーティングが設定されていないのでweb.phpファイルに追加を行う必要があります。新たにEmployeeHomeControllerを作成し、web.phpファイルへルーティングを追加します。
EmployeeHomeController.phpファイルはHomeController.phpファイルをもとに下記のように記述します。
HomeController.phpファイルにはmiddlewareにauthが設定しています。デフォルトではユーザの認証にはGuardのwebを利用するためauthの設定で問題がありませんが、employeeテーブルに存在するユーザのみアクセス可能となるようにauth:employeeを設定します。
Guardの設定
追加したemployeeの設定を行うため/config/auth.phpファイルにEmployee用の追加のGuardを設定します。
guardメソッドの上書き
ユーザ認証の処理が実行されるtraitのRegistersUsersではregisterメソッドの中でguardが設定されています。何も設定しなければwebのGuardが利用されるため、RegisterController.phpファイルでguardメソッドを上書きします。Guardにemployeeを利用することを記述しています。
ファイルの先頭にはAuthを追加します。
view¥employeeの下にhome.blade.phpファイルを作成します。
再度/employee/registerからユーザを登録し、/employee/homeにリダイレクトされれば設定はうまく行われています。
ユーザのログアウト/ログイン
employeeユーザの登録を行うことができましたが、画面右上にあるlogoutをするとパスが/logoutとなりUserのlogoutメソッドが実行されます。
logoutの設定はloginの設定と同じファイルを変更するためにログアウトとログインに関数設定を同時に行うことになります。
レイアウトファイルの複製
home.blade.phpファイルはレイアウトのBladeファイルであるlayouts¥app.blade.phpファイルが使われているのでこのファイルを複製して、app_employee.blade.phpを作成します。
app_employee.blade.phpファイル内のあるrouteメソッドすべてにemployee.を付けます。route(‘login’)であればroute(‘employee.login’)と設定します。
view¥employee¥home.blade.phpファイルの@extendsをappからapp_employeeに変更します。
設定変更によりLogin, Logout, Registerリンクへのパスが/employee/login, /employee/logout, /employee/registerになります。
LoginController.phpの更新
ログイン処理に関してはLoginControllerファイルの更新を行います。
ログイン認証完了後のリダイレクト先をHOMEからEMPLOYEE_HOMEに変更します。この設定はRegisterController.phpファイルでも行いました。
メソッドの上書き
LoginController.phpのメソッドはtraitのAuthenticatesUsersを利用しているのでRegisterContller.phpファイルと同様にguardメソッドとshowLoginFormメソッドをLoginController.phpファイルから上書きしておきます。

ここまでの設定でempolyee/registerで登録したユーザが/employee/loginの朧銀画面を使ってログイン認証を行うことができます。またログインが完了したら/employee/homeにリダイレクトされます。
またログイン後に右上のLogoutのリンクからログアウト処理ができることも確認してください。
empolyee以下のURLへのアクセス
ログインしていない状態で/empolyee/homeにアクセスすると自動で/loginのログイン画面にリダイレクトされます。/loginではなく/employee/loginにリダイレクトされるように変更を行います。
設定を行う前に/loginにリダイレクトされる理由を確認します。
/employee/homeにアクセスするとEmployeeHomeController.phpのindexメソッドが実行されますが、このコントローラーにはmiddlewareのauthが設定されています。auth:employeeのコロン以下はmiddewareのパラメータとして設定できます。
middlewareの確認
authのmiddlewareについてはKernel.phpファイルで設定が行われています。

Authenticate.phpの中身を確認するとredirectToメソッドによりloginへリダイレクトされていることがわかります。
middlewareではhandleが実行されるはずなのになぜredirectToだけ記述されているのか思った方もいるかと思います。AuthenticateクラスはMiddleware(Illuminate\Auth\Middleware\Authenticate)を継承しているのでIlluminate\Auth\Middleware\Authenticateの中身を確認するとその理由がわかります。そのファイルにはhandleメソッドが存在し、認証が行われていない場合はredirectToメソッドが実行されるという流れになっています。
$requestが持つisメソッド
redirectToメソッドの中で/employee/homeに来たアクセスを/employee/loginにリダイレクトさせるための分岐が必要となります。redirectToメソッドには引数で$requestが渡されるので$requestが持つメソッドを知っておく必要があります。
Laravelのドキュメントを見ると分岐に使えそうなisメソッドが存在することがわかります。/employee/*を設定すると/employee/homeからきたリクエストはtrueになります。

設定後ログインしていない状態で/employee/homeにアクセスすると/employee/loginにリダイレクトされます。
ログイン後のloginへのアクセス
ログイン後に再度/employee/loginにアクセスした場合、再度/employee/login画面が表示されてしまいます。
この理由はLoginController.phpファイルにあるmiddleware(‘guest’)にあります。
RedirectIfAuthenticated
middlewareのguestはKernel.phpファイルを確認するとRedirectIfAuthenticatedが実行されています。
RedirectIfAuthenticated.phpファイルのhandleメソッドでは認証の確認後にRouteServiceProviderのHOMEにリダイレクトされる設定となっています。
$guardの値を利用して分岐できるようにEmployeeHomeController.phpファイルのmiddleware(‘guest’)にパラメータのemployeeを追加します。
パラメータを付与するとRedirectIfAuthenticated.phpファイルで$guardの値を取得できるようになります。
$guardの値がemployeeの場合はEMPLOYEE_HOMEである/employee/homeにリダイレクトできるように設定を行います。
/employee/loginだけではなくログインしたユーザがユーザ登録(ユーザ登録画面が表示されない)をできないようにRegisterController.phpファイルのmiddleware(‘guest’)にもパラメータのmiddlewareを追加しておきます。
/loginへのアクセスの場合
/employee/loginでログインしたユーザが/loginにアクセスした場合にどうなるか確認します。
これまでの設定のままではログイン画面が表示されてしまいます。User, Employeeのどちらかにログインしている場合はログアウトするまで別のログイン画面を表示させないために下記のように設定を行うこともできます。
employeeというguardをそのまま記述しているので先程の処理より汎用的ではありませんがAuthのGuardの認証チェックで現在利用しているguardのチェックが成功したら、そのまま設定した先にリダイレクトされます。
Employeeにユーザ登録画面が必要ない場合
Userの場合はだれでも自由に登録を行うことができるためユーザ登録画面が必要ですがEmployeeの場合は従業員を想定しているのでユーザが直接登録を行う画面は必要ではありません。
登録画面を利用したく場合はAuth::routesの引数オプションを設定することで登録画面を表示させるかさせないかを制御することができます。
routesメソッドで設定できる引数オプションは、AuthRouteMethodsファイルを見ることで確認することができます。オプションにはregister, reset , confirm, verifyがあるので自分の環境に合わせて設定を行ってください。
オプションregisterのfalseを設定することによって/employee/registerのルーティングが登録されなくなります。php artisan route:listでも確認することができます。
employessページの作成のために追加したapp_employee.blade.phpファイルの中でregisterへのルーティングがあるかないか判断している箇所があります。
@ifの分岐をregisterではなくemployee.registerに変更する必要があります。
employee/login画面の右上からRegisterがなくなっていることが確認できます。

すべてのoptionを設定した場合は下記のようになります。
ログイン画面のreset機能を使わない場合は、Forgot Your Password?のリンクを表示させないためにはlogin.blade.phpファイルを更新します。
設定後はForget Your Passwordのリンクも消えます。

ここまで本文書で説明するマルチ認証の説明は完了ですが、本文書では設定の変更の理由まで説明を行っているため意図しない動作になっても対応することができるはずです。ぜひマルチ認証にチャレンジしてみてください。