目次

【Laravel 7】マルチ認証(User と Admin で階層分け)

参考:Laravel6でマルチ認証を実装する(UserとAdminの階層を分ける)

パッケージのインストール

  1. composer require laravel/ui:^2.4
  2.  
  3. php artisan ui vue --auth
  4.  
  5. # vue.js を使わない場合は、以下の手順は不要
  6. # NodeJS がない場合はインストール
  7. curl -sL https://rpm.nodesource.com/setup_14.x | bash -
  8. yum -y install nodejs
  9.  
  10. # package.json に記載されたパッケージのインストール
  11. npm install
  12.  
  13. # css、js ファイルのビルド(未圧縮)
  14. npm run dev
  15.  
  16. # css、js ファイルのビルド(圧縮)
  17. npm run production

マイグレーション

以下コマンドで、マイグレーションファイルとモデルファイルを作成。

  1. # Model ファイル作成 (-m オプションでマイグレーションも作成)
  2. php artisan make:model Models/Admin -m

database\migrations に作成された「create_admins_table.php」に「create_users_table.php」の中身をコピペし、admin 用に書き換える。

  1. # マイグレーションの実行
  2. php artisan migrate

モデル

app 直下にある User.php を app\Models の中に 移動。

app\Models\User.php

  1. // ディレクトリを移動したので、namespace を書き換え
  2. namespace App;
  3.  
  4. namespace App\Models;

app\Models\Admin.php

  1. // app\Models\User.php の内容をコピペし、クラス名を書き換える
  2. class User extends Authenticatable
  3.  
  4. class Admin extends Authenticatable

モデルファイルのパスが変わったので、関係するファイルも書き換え。

app\Http\Controllers\Auth\RegisterController.php

  1. use App\User;
  2.  
  3. use App\Models\User;

config\auth.php

  1. 'model' => App\User::class,
  2.  
  3. 'model' => App\Models\User::class,

シーダー

ログイン用のアカウントを作成する。

  1. # シーダー作成
  2. php artisan make:seeder UsersTableSeeder
  3. php artisan make:seeder AdminsTableSeeder

database\seeds\UsersTableSeeder.php

  1. // 追加
  2. use App\Models\User;
  3.  
  4. public function run()
  5. {
  6. // 本番環境以外でのみアカウントを追加
  7. if (config('app.env') !== 'production') {
  8. $user = User::where('email', 'user@example.com')->first();
  9. if (is_null($user)) {
  10. $user = new User();
  11. $user->name = 'user';
  12. $user->email = 'user@example.com';
  13. $user->password = bcrypt('user');
  14. $user->save();
  15. }
  16. }
  17. }

database\seeds\AdminsTableSeeder.php

  1. // 追加
  2. use App\Models\Admin;
  3.  
  4. public function run()
  5. {
  6. // 本番環境以外でのみアカウントを追加
  7. if (config('app.env') !== 'production') {
  8. $admin = Admin::where('email', 'admin@example.com')->first();
  9. if (is_null($admin)) {
  10. $admin = new Admin();
  11. $admin->name = 'admin';
  12. $admin->email = 'admin@example.com';
  13. $admin->password = bcrypt('admin');
  14. $admin->save();
  15. }
  16. }
  17. }

database\seeds\DatabaseSeeder.php

  1. public function run()
  2. {
  3. // 追加
  4. $this->call([
  5. AdminsTableSeeder::class,
  6. UsersTableSeeder::class,
  7. ]);
  8. }
  1. # シーダーをオートローダに登録
  2. php composer dump-autoload
  3.  
  4. # シーディング実行
  5. php artisan db:seed

コンフィグ

認証の設定ファイルをマルチ認証対応に書き換える。

config\auth.php

  1. // デフォルトを user に変更
  2. 'defaults' => [
  3. 'guard' => 'user',
  4. 'passwords' => 'users',
  5. ],
  6.  
  7. 'guards' => [
  8. // web → user に変更
  9. 'user' => [
  10. 'driver' => 'session',
  11. 'provider' => 'users',
  12. ],
  13. // admin を追加
  14. 'admin' => [
  15. 'driver' => 'session',
  16. 'provider' => 'admins',
  17. ],
  18. 'api' => [
  19. 'driver' => 'token',
  20. 'provider' => 'users',
  21. 'hash' => false,
  22. ],
  23. ],
  24.  
  25. 'providers' => [
  26. 'users' => [
  27. 'driver' => 'eloquent',
  28. 'model' => App\Models\User::class,
  29. ],
  30. // admins を追加
  31. 'admins' => [
  32. 'driver' => 'eloquent',
  33. 'model' => App\Models\Admin::class,
  34. ],
  35. ],
  36.  
  37. 'passwords' => [
  38. 'users' => [
  39. 'provider' => 'users',
  40. 'table' => 'password_resets',
  41. 'expire' => 60,
  42. 'throttle' => 60,
  43. ],
  44. // admins を追加
  45. 'admins' => [
  46. 'provider' => 'admins',
  47. 'table' => 'password_resets',
  48. 'expire' => 60,
  49. 'throttle' => 60,
  50. ],
  51. ],

コントローラー

app\Http\Controllers に User ディレクトリを作成し、Auth ディレクトリと HomeController.php をその中に移動。
今回、ログイン機能しか使わないため Auth 内のファイルは LoginController.php 以外を削除。

app\Http\Controllers\User\HomeController.php

  1. // namespace を書き換え
  2. namespace App\Http\Controllers\User;
  3.  
  4. // 追加
  5. use App\Http\Controllers\Controller;
  6.  
  7. public function __construct()
  8. {
  9. // 今回ルーティング側で auth 設定をしているため
  10. // コンストラクタでは何もしない
  11. // コントローラ側で auth を設定したい場合は以下のようにする
  12. // $this->middleware('auth:user');
  13. }
  14.  
  15. public function index()
  16. {
  17. // 書き換え
  18. return view('user.home');
  19. }

app\Http\Controllers\User\Auth\LoginController.php

  1. // namespace の書き換え
  2. namespace App\Http\Controllers\User\Auth;
  3.  
  4. // 追加
  5. use Illuminate\Http\Request;
  6. use Illuminate\Support\Facades\Auth;
  7.  
  8. public function __construct()
  9. {
  10. // 書き換え
  11. $this->middleware('guest:user')->except('logout');
  12. }
  13.  
  14. // 以下追加
  15. protected function guard()
  16. {
  17. return Auth::guard('user');
  18. }
  19.  
  20. public function showLoginForm()
  21. {
  22. return view('user.auth.login');
  23. }
  24.  
  25. public function logout(Request $request)
  26. {
  27. Auth::guard('user')->logout();
  28.  
  29. return $this->loggedOut($request);
  30. }
  31.  
  32. public function loggedOut(Request $request)
  33. {
  34. return redirect(route('user.login'));
  35. }

app\Http\Controllers\User ディレクトリをコピーして Admin ディレクトリを作成。
ディレクトリ内の各ファイルに、以下の置換を行う。

※ AuthenticatesUsers を AuthenticatesAdmins に置換しないように注意

ログイン後のリダイレクト先を Admin 用に書き換える

app\Http\Controllers\Admin\Auth\LoginController.php

  1. protected $redirectTo = RouteServiceProvider::ADMIN_HOME;

ルーティング

routes\web.php

  1. Route::namespace('User')->prefix('user')->name('user.')->group(function(){
  2. Auth::routes([
  3. 'register' => false,
  4. 'reset' => false,
  5. 'verify' => false
  6. ]);
  7.  
  8. Route::middleware('auth:user')->group(function(){
  9. Route::get('home', 'HomeController@index')->name('home');
  10. });
  11. });
  12.  
  13. Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function(){
  14. Auth::routes([
  15. 'register' => false,
  16. 'reset' => false,
  17. 'verify' => false
  18. ]);
  19.  
  20. Route::middleware('auth:admin')->group(function(){
  21. Route::get('home', 'HomeController@index')->name('home');
  22. });
  23. });

その他書き換え

app\Providers\RouteServiceProvider.php

  1. // 書き換え
  2. public const HOME = '/user/home';
  3. // 追加
  4. public const ADMIN_HOME = '/admin/home';

app\Http\Middleware\Authenticate.php

  1. // 追加
  2. use Illuminate\Support\Facades\Route;
  3.  
  4. protected function redirectTo($request)
  5. {
  6. // 書き換え
  7. if (! $request->expectsJson()) {
  8. if (Route::is('user.*')) {
  9. return route('user.login');
  10.  
  11. } elseif (Route::is('admin.*')) {
  12. return route('admin.login');
  13. }
  14. }
  15. }

app\Http\Middleware\RedirectIfAuthenticated.php

  1. public function handle($request, Closure $next, $guard = null)
  2. {
  3. // 書き換え
  4. if (Auth::guard($guard)->check() && $guard === 'user') {
  5. return redirect(RouteServiceProvider::HOME);
  6. } elseif (Auth::guard($guard)->check() && $guard === 'admin') {
  7. return redirect(RouteServiceProvider::ADMIN_HOME);
  8. }
  9. return $next($request);
  10. }

app\Exceptions\Handler.php

  1. // 追加
  2. use Illuminate\Session\TokenMismatchException;
  3.  
  4. public function render($request, Throwable $exception)
  5. {
  6. // 追加
  7. // 419 csrf トークン切れで戻る
  8. if ($exception instanceof TokenMismatchException) {
  9. return back()->withErrors(['time_out' => 'セッションがタイムアウトしました']);
  10. }
  11.  
  12. return parent::render($request, $exception);
  13. }

ビュー

views\layouts にある app.blade.php を app_user.blade.php などにリネーム。

resources\views\layouts\app_user.blade.php

  1. // リンク先などを必要に応じて変更
  2. route('login')
  3.  
  4. route('user.login')
  5.  
  6. route('logout')
  7.  
  8. route('user.logout')

app_user.blade.php をコピーして app_admin.blade.php を作成。
リンク先を route('admin.login') など admin 用に変更。

resources\views 直下に user ディレクトリ作成し、auth ディレクトリと home.blade.php を移動。
home.blade.php で extends しているファイルを変更。

resources\views\user\home.blade.php

  1. // 書き換え
  2. @extends('layouts.app_user')

auth ディレクトリ内にある login.blade.php 以外を削除する。

resources\views\user\auth\login.blade.php

  1. // 書き換え
  2. @extends('layouts.app_user')
  3.  
  4. // リンク先を変更
  5. route('login')
  6.  
  7. route('user.login')

resources\views\user をコピーして admin ディレクトリを作成。
admin ディレクトリ内の各ファイルについて、以下の置換を行う。

一通り作業が完了したので、user、admin それぞれの URL にアクセスしてログイン画面が表示されることを確認。
https://example.com/user/home
https://example.com/admin/home