タイガーラック クリエイティブブログ
2024
May
30

【Laravel】会員・管理者のマルチ認証機能を実装する方法

今回は、弊社で運用しているECサイトで実装したマルチ認証機能について紹介します。

Laravelでは、以下のコマンドで簡単に会員認証機能を実装することができます。

composer require laravel/ui
php artisan ui bootstrap --auth
npm i
npm run dev

ただし、これだけではユーザー側。つまり会員機能のみしか実装されず、同サイト内で認証付きの管理画面を用意しようと思うと、ここから更にひと工夫が必要です。

設定ファイルに管理者用の情報を追加

config/auth.php を開き「guards」で認証管理の方法を設定します。
今回は管理者機能の追加をしたいので「admin」として定義しました。
認証管理についてはセッションまたはトークンから選択することができ、ここではセッションを選択しています。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'customer',
    ],
+   'admin' => [
+       'driver' => 'session',
+       'provider' => 'admin',
+   ],
],

次に同ファイル内の「providers」でモデルの指定を行います。
ここではモデルに「App\Models\Admin」を指定しているので、後でAdminモデルを作る必要があります。

'providers' => [
    'customer' => [
        'driver' => 'eloquent',
        'model' => App\Models\Customer::class,
    ],
+   'admin' => [
+       'driver' => 'eloquent',
+       'model' => App\Models\Admin::class,
+   ],
],

また、パスワード再設定用のテーブルも別途定義しておきましょう。
同ファイル内「passwords」でパスワードリセットテーブルの指定を行います。
今回は、ユーザー側で利用するテーブルと分けたかったため「password_resets_admin」を指定しています。
※別途password_resets_adminテーブルを用意する必要があります。

'passwords' => [
    'customer' => [
        'provider' => 'customer',
        'table' => password_resets,
        'expire' => 60,
        'throttle' => 60,
    ],
+   'admin' => [
+       'provider' => 'admin',
+       'table' => password_resets_admin,
+       'expire' => 60,
+       'throttle' => 60,
+   ],
],

認証時のリダイレクト処理を編集

会員がログインした場合は /mypage、管理者がログインした場合は /admin/home へリダイレクトさせたいため、ログインが成功した場合のリダイレクト先を分ける処理が必要です。
app/Http/Middleware/RedirectIfAuthenticated.php を編集します。

public function handle(Request $request, Closure $next, ...$guards)
{
    $guards = empty($guards) ? [null] : $guards;

    foreach ($guards as $guard) {
        if ($guard == "admin" && Auth::guard($guard)->check()) {
            return redirect('admin/home');
        }

        if (Auth::guard($guard)->check()) {
            return redirect(RouteServiceProvider::HOME);
        }
    }

    return $next($request);
}

また、認証に失敗した場合のリダイレクト先も分けたいため、app/Exceptions/Handler.php を編集しておきましょう。

protected function unauthenticated($request,Throwable $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['message' => $exception->getMessage()],401);
    }
    if ($request->is('admin') || $request->is('admin/*')) {
        return redirect()->guest('/admin/login');
    }
    return redirect()->guest($exception->redirectTo ?? route('login'));
}

これで管理画面へのログインに失敗した場合は、再び管理画面のログインページへリダイレクトされるようになりました。

管理者テーブルとモデルの作成

ここまで準備ができたら、管理者情報を保存するテーブルと、それに関連するモデルファイルを作成します。

まずはDBにテーブルを用意します。
次のコマンドを打ってマイグレーションファイルを作成しましょう。

php artisan make:migration create_admins_table

出来上がったマイグレーションファイルにテーブルのカラムを定義します。
システムの仕様によるかと思いますが、今回は主に名前、メールアドレス、パスワードを管理するシンプルな構成にしました。

public function up()
{
    Schema::create('admins', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name', 255);
        $table->string('email', 255);
        $table->string('password');
        $table->rememberToken();
        $table->integer('status');
        $table->softDeletes();
        $table->timestamps();

        $table->unique(['email', 'deleted_at']);
    });
}

migrateコマンドを実行してテーブルを作成します。

php artisan migrate

テーブルが完成したら、次にモデルファイルを用意します。

php artisan make:model Admin

管理者用のモデルファイルは、Illuminate/Foundation/Auth/User を継承すると便利です。

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User;
use Illuminate\Database\Eloquent\SoftDeletes;

class Admin extends User
{
    use SoftDeletes;
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
}

コントローラ・ビューファイルの編集

冒頭のコマンド(php artisan ui bootstrap –auth)で既に会員認証機能で利用するコントローラ、ビューファイルが出来上がっているので、これをコピーして中身に手を加えて管理者用のファイルを用意していきます。

管理者登録フォーム

まずコントローラから。
app/Http/Controllers/Auth/RegisterController.php を app/Http/Controllers/Admin/RegisterController.php にコピーして編集します。

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Auth\Events\Registered;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Admin;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '/admin/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin');
    }

    protected function guard()
    {
        return Auth::guard('admin');
    }

    /**
     * Show the application registration form.
     *
     * @return \Illuminate\View\View
     */
    public function showRegistrationForm()
    {
        return view('auth.register', ['authgroup' => 'admin']);
    }

    /**
     * Handle a registration request for the application.
     *
     * @param  Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    public function register(Request $request)
    {
        $this->validator($request->all(), $request)->validate();

        event(new Registered($user = $this->create($request->all())));

        Auth::guard('admin')->login($user);

        if ($response = $this->registered($request, $user)) {
            return $response;
        }

        return $request->wantsJson()
                    ? new JsonResponse([], 201)
                    : redirect($this->redirectPath());
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email:dns', 'max:255', 'unique:admins'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\Customer
     */
    protected function create(array $data)
    {
        return Admin::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
}

ビューは、
resources/views/auth/register.blade.php を resources/views/admin/register.blade.php にコピーし、フォームの送信先を編集します。

<form method="POST" action="{{ url('admin/register') }}"> 

ログインフォーム

app/Http/Controllers/Auth/LoginController.php を app/Http/Controllers/Admin/LoginController.php にコピーして編集します。

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Throwable;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/admin/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin')->except('logout');
    }

    protected function guard()
    {
        return Auth::guard('admin');
    }
}

続いてビューファイル。
resources/views/auth/login.blade.php を resources/views/admin/login.blade.php へコピーして編集します。

<form method="POST" action="{{ url('admin/login') }}">

フォームの送信先を変更しておきます。

管理画面TOP

ログイン後のホーム画面を作成します。

resources/views/home.blade.php を resources/views/admin/home.blade.php へコピーして編集します。
※ホーム画面はデザインによるため割愛
※管理画面内でログアウトボタンなどを設置する場合はリンク先のルーティングに注意!

ルーティングの設定

最後に管理画面認証ページ周りのルーティングを設定して完了です。

Route::view('/admin/login', 'admin/login');
Route::post('/admin/login', [App\Http\Controllers\Admin\LoginController::class, 'login']);
Route::view('/admin/register', 'admin/register');
Route::post('/admin/register', [App\Http\Controllers\Admin\RegisterController::class, 'register']);
Route::post('/admin/logout', [App\Http\Controllers\Admin\LoginController::class, 'logout'])->name('admin/logout');

ここまで手順は長かったですが、ほとんどベースファイルをコピペして編集するだけなので、そこまで重たい作業ではなかったはずです。
これでマルチ認証機能を実装することができました。

このカテゴリの最新記事

関連記事

SHOP LIST

タイガーラック株式会社

〒577-0056
大阪府東大阪市長堂1-3-14 TOKUYASU Bld.