k.watanabe技術者ブログ

k.watanabe

管理画面の作成とマルチ認証について

はじめに

記事を登録するための管理画面を作成しました。マルチ認証についての内容もまとめてみました。


参考記事:Laravel9でマルチ認証(一般ユーザーと管理者で別々のログイン機能)を実装する

マルチ認証とは

例えばECサイトでは商品や顧客情報などを管理する管理画面の他に、ユーザーでも認証機能が備わっているケースがあります。

この場合は管理画面のログインとユーザーのログインで二つの認証機能が備わっていることになります。その仕組みを実現しようとすると、ユーザーはusersテーブル、管理者はadminsテーブルに登録して管理する方法が考えられます。

このように、テーブルをそれぞれに分けてログイン機能を複数設けることがマルチ認証です。

手順1: 管理画面を作るのに必要なファイルを作成

このコマンドだけでModelとControllerとmigrationファイルを一度に作成出来ます。


  1. php artisan make:model Admin -mcr

手順2: マイグレーションファイルを編集する

管理者を登録するAdminテーブルを作成するためにマイグレーションファイルを以下のように編集します。もちろん必要に応じてカラムを追加します。


database/migrations/2023_07_18_165316_create_admins_table.php

  1. <?php
  2. use Illuminate\Database\Migrations\Migration;
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Support\Facades\Schema;
  5. return new class extends Migration
  6. {
  7.     /**
  8.      * Run the migrations.
  9.      */
  10.     public function up(): void
  11.     {
  12.         Schema::create('admins', function (Blueprint $table) {
  13.             $table->id();
  14.             $table->string('email')->unique();
  15.             $table->string('password');
  16.             $table->rememberToken();
  17.             $table->timestamps();
  18.         });
  19.     }
  20.     /**
  21.      * Reverse the migrations.
  22.      */
  23.     public function down(): void
  24.     {
  25.         Schema::dropIfExists('admins');
  26.     }
  27. };

手順3 モデルクラスの作成

マイグレーションを実行し、Adminモデルクラスを作成する


  1. $ php artisan migrate

ちなみにローカル環境ならロールバッグした上でマイグレーションしたい場合はこのコマンドで出来ます。

  1. php artisan migrate:refresh --seed

手順4 モデルクラスを認証用に編集する

認証するためにAuthenticatableクラスを継承する。デフォルトではクラス名のextendsの箇所がModelとなっているので、ModelをAuthenticatableに変える。useすることも忘れずに。


app/Models/Admin.php

  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Factories\HasFactory;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Foundation\Auth\User as Authenticatable;
  6. use Laravel\Sanctum\HasApiTokens;
  7. use Illuminate\Notifications\Notifiable;
  8. class Admin extends Authenticatable
  9. {
  10.     use HasApiTokens, HasFactory, Notifiable;
  11.     
  12.     protected $fillable = [
  13.         'email',
  14.         'password',
  15.         'url'
  16.       ];
  17.     protected $hidden = [
  18.     'password',
  19.     'remember_token',
  20.     ];
  21.     protected $casts = [
  22.         'email_verified_at' => 'datetime',
  23.       ];
  24.       
  25. }

この一文を追加する。

  1. use Illuminate\Foundation\Auth\User as Authenticatable;

編集前: デフォルトの状態

  1. class Admin extends Model
  2. {

編集後 ModelをAuthenticatableに変更

  1. class Admin extends Authenticatable
  2. {

手順5 ログインページの作成

マルチ認証を実装するために管理者用とユーザー用の二つのログインページを用意します。簡素なので、後でAdminLTEやBreezeなどでデザインも工夫しようと思います。

管理画面ログイン ユーザーログイン

ルーティングはこのように管理者はadmin、ユーザーはauthでファイルを分けています。

route/admin.php

  1. Route::prefix('admin')->group(function () {
  2.     Route::get('login', [LoginController::class, 'index'])->name('admin.login.index');
  3.     Route::post('login', [LoginController::class, 'login'])->name('admin.login.login');

route/auth.php

  1. Route::middleware('guest')->group(function () {
  2.     Route::get('login', [AuthenticatedSessionController::class, 'create'])
  3.                 ->name('login');
  4.     Route::post('login', [AuthenticatedSessionController::class, 'store']);

手順6 コンフィグファイルの「ガード」と「プロバイダ」の設定

マルチ認証するために、コンフィグでガードを設定します。ここがマルチ認証で重要な部分になります。


config/auth.php

  1. 'providers' => [
  2.         'users' => [
  3.             'driver' => 'eloquent',
  4.             'model' => App\Models\User::class,
  5.         ],
  6.         'admins' => [
  7.             'driver' => 'eloquent',
  8.             'model' => App\Models\Admin::class,
  9.         ],
  10.         'members' => [
  11.             'driver' => 'eloquent',
  12.             'model' => App\Models\User::class,
  13.         ],
  14.     ],

adminsのkeyの場合は、Adminモデルを使って認証し、membersの場合はUserモデルを使って認証させるようにしています。

  1. 'guards' => [
  2.         'web' => [
  3.             'driver' => 'session',
  4.             'provider' => 'users',
  5.         ],
  6.         'members' => [
  7.             'driver' => 'session',
  8.             'provider' => 'users',
  9.         ],
  10.         'admins' => [
  11.             'driver' => 'session',
  12.             'provider' => 'admins',
  13.         ],
  14.     ],

guardsは後述しますが、認証するために使うkeyとなります。ここでproviderがadminの場合は上述したadminモデルを使って認証するという意味です。

手順7 コントローラー側で認証を制御する

コントローラー側で管理者とユーザーでそれぞれ認証をチェックする処理を記述します。


Controllers/Admin/LoginController.php

  1. //ログイン処理
  2.   public function login(Request $request)
  3.   {
  4.     $credentials = $request->only(['email', 'password']);
  5.    
  6.     //ユーザー情報が見つかったらログイン
  7.     if (Auth::guard('admins')->attempt($credentials)) {
  8.       //ログイン後に表示するページにリダイレクト
  9.       return redirect()->route('admin.dashboard')->with([
  10.         'login_msg' => 'ログインしました。',
  11.       ]);
  12.     }
  13.     //ログインできなかったときに元のページに戻る
  14.     return back()->withErrors([
  15.       'login' => ['ログインに失敗しました'],
  16.     ]);
  17.   }

7行目のguardの記述でログインページで入力したメールアドレスとパスワードがAdminモデルを介してテーブルに登録されているかどうかをチェックしています。

ユーザーの場合も先ほどconfigに定義したmembersをguardで指定すれば、Userモデルに対して認証のチェックを行えます。

Controllers/Auth/AuthenticatedSessionController.php

  1.  public function index(Request $request)
  2.     {
  3.         if (Auth::guard('members')->attempt($request->only(['email', 'password']))) {
  4.             return redirect()->route('user.dashboard')->with([
  5.                 'login_msg' => 'ログインしました。',
  6.             ]);
  7.         }
  8.         //ログインできなかったときに元のページに戻る
  9.         return back()->withErrors([
  10.             'login' => ['ログインに失敗しました'],
  11.         ]);
  12.     }

ユーザーの場合はmembers、管理者の認証の場合はadminsを指定するだけですね。このやり方を応用すれば他のモデルクラスでも認証チェックが出来るようになります。そういった使い方がマルチ認証です。

  1. if (Auth::guard('members')->attempt($credentials)) {
  1. if (Auth::guard('admins')->attempt($credentials)) {
記事一覧に戻る

プロフィールに戻る