2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】スターターキットを使用しないマルチログイン認証の実装方法

Posted at

この記事に書いてあること

マルチログイン認証の実装方法

利用バージョン

Laravel8

モデル&マイグレーションをつくる

管理者用のモデルとマイグレーションをつくる
※一般ユーザー用のモデルとマイグレーションはデフォルトで入っているものを利用

以下のコマンドを実行

php artisan make:model Admin -m

モデルの設定

app/Models/User.phpの中身をまるっとAdmin.phpにコピペ
クラス名の変更を必ずする

app/Models/Admin.php
<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

//クラス名変える
class Admin extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
    //省略
}

マイグレーションをつくる

モデルと同じように、database/migrations/create_users_table.phpの中身をまるっと、create_admins_table.phpへコピペ
テーブル名の変更を必ずする

database/migrations/create_admins_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAdminsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //テーブル名変更
        Schema::create('admins', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //テーブル名変更
        Schema::dropIfExists('admins');
    }
}

テストデータをつくる

管理者と一般ユーザーのテストデータを作ります

以下コマンドでシーダーファイルを作成

php artisan make:seed MultiAuthTableSeeder

Seederファイル(テストデータの設定ファイル)が作成されるので中身を以下のように変更

database/seeders/MultiAuthTableSeeder.php
<?php

namespace Database\Seeders;

use App\Models\Admin;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Database\Seeder;

class MultiAuthTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $init_users = [
            [
                'name' => '一般ユーザー',
                'email' => 'user@test.com',
                'password' => 'secret',
            ],
        ];

        foreach($init_users as $init_user) {

            $user = new User();
            $user->name = $init_user['name'];
            $user->email = $init_user['email'];
            $user->password = Hash::make($init_user['password']);
            $user->save();

        }

        $init_admins = [
            [
                'name' => '管理者',
                'email' => 'admin@test.com',
                'password' => 'secret',
            ],
        ];

        foreach($init_admins as $init_admin) {

            $admin = new Admin();
            $admin->name = $init_admin['name'];
            $admin->email = $init_admin['email'];
            $admin->password = Hash::make($init_admin['password']);
            $admin->save();

        }
    }
}

SeederファイルをDatabaseSeederに登録

database/seeders/DatabaseSeeder.php
public function run()
{
    $this->call(MultiAuthTableSeeder::class);
}

以下のコマンドでテーブルとテストデータをデータベースに作成

php artisan migrate:fresh --seed

各モデルでログインできるように設定する

複数のログイン機能をつくるには、ガード・プロバイダ・モデルがそれぞれ必要になります。
ここら辺の説明はこちらの記事を参照ください。

モデルはさっき作ったので、ガードとプロバイダを追加していきます。
これらはconfig/auth.phpで管理されているので、そちらを編集していく。

config/auth.php
<?php

return [
    //省略
    
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        //追加
        'users' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        //追加
        'admins' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],
    
    //省略
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        //追加
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],
    
    //省略
];

コントローラーをつくる

以下のコマンドを実行

artisan make:controller MultiAuthController

作成されたコントローラを以下のように変更

メソッドの役割

  • showLoginForm():ブラウザでメールアドレスやパスワードを入力するページ
  • showUserDashBoard():一般ユーザーログイン後のダッシュボード
  • showAdminDashBoard():管理者ログイン後のダッシュボード
  • login():ログイン画面からのフォーム入力情報送信先
  • logout():ダッシュボードページからのログアウト情報送信先

LoginとLogoutメソッドの定義方法はドキュメントにそれぞれ記載があるので、それらをまるっとコピペしてます。
Loginメソッド
Logoutメソッド

app/HTTP/Controllers/MultiAuthController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class MultiAuthController extends Controller
{
    public function showLoginForm() {
        return view('multi_auth.login');
    }

    public function showUserDashBoard() {
        return view('multi_auth.userDashBoard');
    }

    public function showAdminDashBoard() {
        return view('multi_auth.adminDashBoard');
    }

    /**
     * 認証の試行を処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request)
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required'],
        ]);
        $credentials = $request->only(['email', 'password']);
        $guard = $request->guard;

        if (Auth::guard($guard)->attempt($credentials)) {
            $request->session()->regenerate();

            return redirect($guard.'/dashboard');
        }

        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ]);
    }

    /**
     * ユーザーをアプリケーションからログアウトさせる
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
    */
    public function logout(Request $request)
    {
        Auth::logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return redirect('multi_login');
    }
}

ビューをつくる

showLoginForm()の中で指定したビュー

resources/views/multi_auth/login.blade.php
<html>
<head>
    <link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    <form method="POST" action="multi_login">
        @csrf
        <div class="p-3">
            @foreach ($errors->all() as $error)
                <li class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-3">{{$error}}</li>
            @endforeach

            <label class="block">メールアドレス</label>
            <input class="border rounded mb-3 px-2 py-1" type="text" name="email">
            <label class="block">パスワード</label>
            <input class="border rounded mb-3 px-2 py-1" type="password" name="password">
            <label class="block">ユーザータイプ</label>
            <select name="guard" class="border rounded px-2 py-1 mb-5">
                <option value="">選択してください</option>
                <option value="users">一般ユーザー</option>
                <option value="admins">管理者</option>
            </select>
            <br>
            <button class="bg-blue-500 text-white rounded px-3 py-2" type="submit">ログイン</button>
        </div>
    </form>
</body>
</html>

showUserDashBoard()の中で指定したビュー

resources/views/multi_auth/userDashBoard.blade.php
<html>
<head>
    <link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    一般ユーザーのダッシュボード
    <form method="POST" action="/multi_login/logout">
        @csrf
        <div class="p-3">
            <button class="bg-blue-500 text-white rounded px-3 py-2" type="submit">ログアウト</button>
        </div>
    </form>
</body>
</html>

showAdminDashBoard()の中で指定したビュー

resources/views/multi_auth/adminDashBoard.blade.php
<html>
<head>
    <link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    管理者のダッシュボード
    <form method="POST" action="/multi_login/logout">
        @csrf
        <div class="p-3">
            <button class="bg-blue-500 text-white rounded px-3 py-2" type="submit">ログアウト</button>
        </div>
    </form>
</body>
</html>

ルートをつくる

ミドルウェアのauthは:に続けてコンフィグで設定したユーザー名を記載
自動的にそのユーザーのログインを判別してくれる

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

// マルチ認証
// ログイン
Route::get('multi_login', [\App\Http\Controllers\MultiAuthController::class, 'showLoginForm']);
Route::post('multi_login', [\App\Http\Controllers\MultiAuthController::class, 'login']);

// ログアウト
Route::post('multi_login/logout', [\App\Http\Controllers\MultiAuthController::class, 'logout']);

// ログイン後のページ
Route::prefix('users')->middleware('auth:users')->group(function(){
    Route::get('dashboard', [\App\Http\Controllers\MultiAuthController::class, 'showUserDashBoard']);
});
Route::prefix('admins')->middleware('auth:admins')->group(function(){
    Route::get('dashboard', [\App\Http\Controllers\MultiAuthController::class, 'showAdminDashBoard']);
});

ログインしていないときの強制リダイレクトをつくる

デフォルトだと、リダイレクト先が通常のログインページになっているので変更

app/Http/Middleware/Authenticate.php
<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return 'multi_login';//変更
        }
    }
}

おしまい。

所感

認証の仕組みを俯瞰して理解すると簡単・シンプルに実装できました。

参考記事

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?