Laravel 5.8 でMulti-Auth

WEBシステム開発では多くの場合、一般ユーザと管理者の編集者が必要となるので
前回のUSERログインとは別にADMINログインを追加してみましょう。
管理者の登録やパスワードリセットは不要とします。

開発環境

Laradock
Laravel 5.8
MySQL 5.7

config/auth.phpの設定

config/auth.php

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
        /** 以下を追加 **/
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
        /** ここまで **/
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        /** 以下を追加 **/
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
        /** ここまで **/
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        /** 以下を追加 **/
        'admins' => [
            'provider' => 'admins',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        /** ここまで **/
    ],

adminsテーブル作成

【マイグレーションファイル作成】

PS C:\laravel\laradock> docker-compose exec workspace bash
root@7b33d48aadc4:/var/www# php artisan make:migration create_admins_table

【マイグレーションファイル編集】

database/migrations/xxxxxx_create_users_table.phpを参考に作成する。

database/migrations/xxxxxx_create_admins_table.php

        Schema::create('admins', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

【マイグレーション】

root@7b33d48aadc4:/var/www# php artisan migrate

【Adminモデル作成】

root@7b33d48aadc4:/var/www# php artisan make:model Models/Admin

【Adminモデル編集】

app/Models/Admin.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];
}

認証エラー時の対応

app/Exceptions/Handler.phpに未ログイン時の対応(unauthenticated)を設定。
Illuminate\Auth\AuthenticationExceptionを継承しているのでunauthenticatedメソッドをオーバーライド。

app/Exceptions/Handler.php

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

/** 以下追加 **/
use Request;
use Response;
use Illuminate\Auth\AuthenticationException;
/** ここまで **/

class Handler extends ExceptionHandler
{
    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }

    /** 以下追加 **/
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        // JSONの対応
        if($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        // Adminの対応
        if(in_array('admin', $exception->guards())){
            return redirect()->guest('admin/login');
        }
        // Userの対応
        return redirect()->guest(route('login'));
    }
    /** ここまで **/
}

ルーティング設定

routes/web.php

/** 以下追加 **/
// Admin
Route::group(['prefix' => 'admin'], function(){
    // AdminHome
    Route::get('home', 'Admin\HomeController@index')->name('admin.home');
    //login&logout
    Route::get('login', 'Admin\LoginController@showLoginForm')->name('admin.login');
    Route::post('login', 'Admin\LoginController@login')->name('admin.login');
    Route::post('logout', 'Admin\LoginController@logout')->name('admin.logout');
});
/** ここまで **/

コントローラーの作成

【ディレクトリ構成】

app
 ┗ Http
    ┗ Controllers
       ┠ Admin							// 追加
       ┃  ┠ HomeController.php		// 追加
       ┃  ┗ LoginController.php		// 追加
       ┠ Auth
       ┃  ┠ ForgotPasswordController.php
       ┃  ┠ LoginController.php		// 変更
       ┃  ┠ RegisterController.php
       ┃  ┠ ResetPasswordController.php
       ┃  ┗ VerificationController.php
       ┠ Controller.php
       ┗ HomeController.php

【Adminディレクトリ作成】

root@7b33d48aadc4:/var/www# mkdir app/Http/Controllers/Admin

【Admin/HomeController.php作成】

※app/Http/Controllers/HomeController.phpをコピーして編集。

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;	// 追記

class HomeController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:admin');	// 変更
    }

    public function index()
    {
        return view('admin.home');	// 変更
    }
}

【Admin/LoginController.php作成】

app/Http/Controllers/Auth/LoginController.phpをコピーして編集。
※Adminだけログアウトする

<?php

namespace App\Http\Controllers\Admin;	// 変更

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;	// 追加※

class LoginController extends Controller
{

    use AuthenticatesUsers;

    protected $redirectTo = '/admin/home';	// 変更

    public function __construct()
    {
        $this->middleware('guest:admin')->except('logout');	// 変更
    }
    /** 以下追記 **/
    public function showLoginForm()
    {
        return view('admin.login');
    }

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

    public function logout(Request $request)
    {
        \Auth::guard('admin')->logout();
        return redirect('/admin/login');
    }
    /** ここまで **/

}

【Auth/LoginController.php修正】

※Userだけログアウト

use Illuminate\Http\Request;	// 追記

class LoginController extends Controller
{
	・・・
    public function __construct()
    {
        //$this->middleware('guest')->except('logout');
        $this->middleware('guest:user')->except('logout');	// 変更
    }
    /** 以下追記 **/
    public function showLoginForm()
    {
        return view('auth.login');
    }

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

    public function logout(Request $request)
    {
        \Auth::guard('user')->logout();
        return redirect('/login');
    }
    /** ここまで **/

【User側HomeController.php修正】

※Userだけログアウト

    public function __construct()
    {
        // $this->middleware('auth');
        $this->middleware('auth:user');
    }

ビュー作成

【レイアウト作成】

※resources/views/layouts/app.blade.phpをコピーしてresources/views/layouts/admin.blade.phpを作成

route変更
route(‘login’) -> route(‘admin.login’)
route(‘logout’) -> route(‘admin.logout’)

登録等の不要コード削除

【admin/home.blade.php】

resources/views/adminディレクトリを作成。
resources/views/home.blade.phpをコピーしてresources/views/admin/home.blade.phpを作成

継承元変更
@extends(‘layouts.app’) -> @extends(‘layouts.admin’)

【admin/login.blade.php】

resources/views/auth/login.blade.phpをコピーしてresources/views/admin/login.blade.phpを作成

継承元変更
@extends(‘layouts.app’) -> @extends(‘layouts.admin’)
route変更
route(‘login’) -> route(‘admin.login’)

Forgot Your Password?等不要コード削除

補足:adminsテーブルにデータ投入

root@7b33d48aadc4:/var/www# php artisan tinker

App\Models\Admin::create([
'name' => 'test',
'email' => 'xxxxxxxx@gmail.com',
'password' => \Hash::make('123456789')
]);

補足:同時に連続ログイン

419 Page Expired

が発生するがcsrf対策のtokenが同じだからしょうがないか・・・

補足:ログイン情報取得

use Illuminate\Support\Facades\Auth;

$user = Auth::user();
$user->id;
$user->name;
use Illuminate\Support\Facades\Auth;

$admin = Auth::user();
$admin->id;
$admin->name;