Tips

『Laravel5.2』入門 Multi-Auth認証の基本 PHPフレームワーク連載第4回

『Laravel5.2』入門 Multi-Auth認証の基本 PHPフレームワーク連載第4回

『Laravel5.2』入門 Multi-Auth認証の基本 PHPフレームワーク連載第4回

はじめに

PHPフレームワークの中で人気急上昇中の「Laravel」に、足りない足りないと言われてきた機能が「Multi-Auth」です。「Multi-Auth」というのは、たとえば一般ユーザと管理ユーザが別テーブルで管理されている場合に、それぞれ個別の認証を実現する機能です。「Laravel5.1」まではこの機能はデフォルトでは用意されていなかったので別途組み込みが必要でしたが、「Laravel5.2」からはこの機能がデフォルトで用意されるようになりました。管理者の中でも役割(ロール)が分かれているような場合は、別途その値をチェックする処理が必要になりますが、今回はひとまず、一般ユーザと管理ユーザを別で管理する場合のサンプルを作成してみたいと思います。

Laravel5.2を使ったログインサンプルの概要

今回は管理者の登録、パスワードリセットの機能などは省略します。
管理者のデータは初期登録しておき、ログイン/ログアウトができることを確認します。
以下の内容で作成していきます。

テーブル定義(Model)

テーブル:
users(デフォルトで用意されているものを使います)
admins(usersと同構造のものを作成します)

ルーティング

Method URI Action Middleware
GET|HEAD admin/home AdminHomeController@index web,auth:webadmin
POST admin/login AdminAuthController@login web,guest:webadmin
GET|HEAD admin/login AdminAuthController@showLoginForm web,guest:webadmin
GET|HEAD admin/logout AdminAuthController@logout web
GET|HEAD home HomeController@index web,auth
POST login Auth\AuthController@login web
GET|HEAD login Auth\AuthController@showLoginForm web
GET|HEAD logout Auth\AuthController@logout web
POST password/email Auth\PasswordController@sendResetLinkEmail web,guest
POST password/reset Auth\PasswordController@reset web,guest
GET|HEAD password/reset/{token?} Auth\PasswordController@showResetForm web,guest
GET|HEAD register Auth\AuthController@showRegistrationForm web
POST register Auth\AuthController@register web

※多い・・・と思うかもしれませんが、安心してください。artisanコマンドでadmin以外はあっという間にできます。

ブレード(View)

今回作るのは以下の管理者側のblade2つ。
・admin/login.blade.php
・admin/home.blade.php
※一般ユーザ側はルーティング同様、artisanコマンドで自動生成してくれます。

Laravel5.2を使ったログインサンプルの作成手順

1.LaravelのProject作成

$ composer create-project “laravel/laravel” –prefer-dist lara5.2.loginsystem

2.DB作成&「.env」ファイル修正

$ mysql -u root -p
mysql> create database loginsystem;

※上記のDB名、ユーザ・パスワードに合わせて.env修正

3.artisanのmake:auth実行

$ php artisan make:auth
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/auth/login.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/auth/register.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/auth/passwords/email.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/auth/passwords/reset.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/auth/emails/password.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/layouts/app.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/home.blade.php
Created View: /home/ubuntu/workspace/lara5.2.membersystem/resources/views/welcome.blade.php
Installed HomeController.
Updated Routes File.
Authentication scaffolding generated successfully!

このコマンドで自動で実行されたことは以下の通り。

・HomeController.phpが生成される
・routes.phpが以下のように更新される

Route::group(['middleware' => 'web'], function () {
	Route::auth();
	Route::get('/home', 'HomeController@index');
});

※Route::groupの記述が2つになるので既存分は消してよいと思います。
※Route::auth()という記述で、実は以下のルーティングを定義してくれています。

$this->get('login', 'Auth\AuthController@showLoginForm');
$this->post('login', 'Auth\AuthController@login');
$this->get('logout', 'Auth\AuthController@logout');
$this->get('register', 'Auth\AuthController@showRegistrationForm');
$this->post('register', 'Auth\AuthController@register');
$this->get('password/reset/{token?}', 'Auth\PasswordController@showResetForm');
$this->post('password/email', 'Auth\PasswordController@sendResetLinkEmail');
$this->post('password/reset', 'Auth\PasswordController@reset');

※以下コマンドで確認できます。
$ php artisan route:list

4.デフォルトで用意されているmigrationを流す

Laravel5ではデフォルトでユーザテーブル用のmigrationが用意されているのでこれを実行。

$ php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table

実行できたらusersテーブルとpassword_resetsテーブルが出来上がっていることを確認。

5.http://[Your-Laravel-Root-Domain]/registerにアクセス

登録画面が表示される、はず。
Name、E-Mail Address、Password、Confirm Passwordを入力して「Register」をクリック。
無事登録できるとログイン済みの状態でトップページへ遷移。

なんとこれだけであっという間に基本のユーザ単体のログイン機能は完成です。
この基本のユーザ認証を元に、Adminユーザのログイン認証を作成していきましょう。

6.Admin用テーブルを作成するmigrateを準備

$ php artisan make:migration create_admins_table

migrateが出来上がるので、中身をusersテーブルのmigrateからコピペ。

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

※テーブル名は「admins」に変えることを忘れずに。

7.Admin用migrateを流す

$ php artisan migrate

adminsテーブルが出来上がる。mysqlコマンドで確認しておく。

8.adminsテーブル用Seedを作成

$ php artisan make:seeder AdminTableSeeder

ひとまず以下のように1管理者のユーザを登録するSeedを作成。

    public function run()
    {
        DB::table('admins')->truncate();
        DB::table('admins')->insert([
            'name' => 'テスト',
            'email' => 'admin@example.com',
            'password' => bcrypt('adminpass'),
        ]);
    }

DatabaseSeeder.phpに上記seedを追記することを忘れずに。

public function run()
    {
        // $this->call(UserTableSeeder::class); ←今回こちらは流さなくてもOK
        $this->call(AdminTableSeeder::class);
    }

9.Seedを流す

$ php artisan db:seed

これでadmin側のDB準備完了。

10.Admin用認証ルールの作成

「app/config/auth.php」を編集。以下のようにguardsを追加する。

    'guards' => [
        'web' => (省略),
        'api' => (省略),
        'webadmin' => [ //←以降追加
		'driver' => 'session',
		'provider' => 'adminusers',
	],
    ],
    'providers' => [
        'users' => (省略),
        'adminusers' => [ //←以降追加
		'driver' => 'eloquent',
		'model' => App\Admin::class,
	],
        // 'users' => (省略),
    ],
    'passwords' => [
        'users' => (省略),
        'adminusers' => [ //←以降追加
		'provider' => 'adminusers',
		'email' => 'auth.emails.password',
		'table' => 'password_resets',
		'expire' => 60,
	],
    ],

補足.「auth」Middlewareについて
Laravel4ではFilterと呼ばれていた機能がLaravel5ではMiddlewareです。Filterの方がイメージが付きやすいかもしれませんが、この機能はリクエストを処理する前に(または後に)そのリクエストが適切かをフィルタリングする機能です。
routes.phpかコントローラでmiddlewareを指定することで、どのリクエストに対してどのMiddlewareを噛ますかを指定することができ、その際Middlewareのエイリアスを指定します。Middlewareの実クラスとエイリアスの関連が「Kernel.php」に指定されています。
今回使用するauth認証用Middlewareクラスは
「’auth’ => \App\Http\Middleware\Authenticate::class,」
と指定されています。
「App\Http\Middleware\Authenticate.php」を見てみると、
handleメソッドが定義されています。このメソッドが
第1引数でrequestを受取り、
第2引数でフィルタリング後の処理を受取り、
第3引数以降でMiddleware指定時に渡されるパラメータを受取ります。
今回は第3引数は「guard」の種類を指定することができます。
このguardとは何かというと、何の認証を使用するかの指定になります。
どういう認証を用意するかを指定しているのが、「app/config/auth.php」になります。

11.ルートの追加

routes.phpにadmin用のルーティングを追記していく。また、各リクエストに対してMiddlewareを噛ましておく必要がある(コントローラがわでやっても可。後述)。

Route::group(['middleware' => 'web'], function () {
    Route::group(['middleware' => 'guest:webadmin'], function () { //←このグループで括る
        Route::get('/admin/login','AdminAuthController@showLoginForm');
        Route::post('/admin/login','AdminAuthController@login');
    });
    Route::group(['middleware' => 'auth:webadmin'], function () { //←このグループで括る
        Route::get('/admin/home','AdminHomeController@index');
    });
    Route::get('/admin/logout','AdminAuthController@logout');
    
    Route::auth();
    Route::get('/home', 'HomeController@index');
});

※上記のようにMiddleware名の後にコロン区切りで引数を渡すことで、Middleware側のhandleメソッドの第3引数にこの値が渡されることになります。
※グループで括らなくてもよいですが、今後画面が増えていくことを考えるとグルーピングしておいた方がよいと思われます。

Middlewareの噛ませ方は、routes.phpで指定する方法とコントローラで指定する方法がある。
上記はroutes.php側で指定する用だが、もしroutes.phpでは指定せずにコントローラで指定するのであれば、例えば以下のようにする。

Route::group(['middleware' => 'web'], function () {
    Route::get('/admin/login','AdminAuthController@showLoginForm'); //←追加
    Route::post('/admin/login','AdminAuthController@login'); //←追加
    Route::get('/admin/home','AdminHomeController@index'); //←追加
    Route::get('/admin/logout','AdminAuthController@logout'); //←追加

    Route::auth();
    Route::get('/home', 'HomeController@index');
});

12.Middlewareの修正

ルーティングで指定されているauth(Authenticate.php)とguest(RedirectIfAuthenticated.php)のmiddlewareを修正していく。
$guardが「webadmin」になっているものは、リダイレクト先を変えていく。

【Authenticate.php】

    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->guest()) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            } else {
                if($guard == 'webadmin'){ //←このif文を追加
                    return redirect()->guest('/admin/login');
                }
                return redirect()->guest('login');
            }
        }

        return $next($request);
    }

【RedirectIfAuthenticated.php】

    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            if($guard == 'webadmin'){ //←このif文を追加
                return redirect('/admin/home');
            }
            return redirect('/admin/home');
        }

        return $next($request);
    }
ここからビュー、モデル、コントローラを作成していきます。
順番はどうでもいいのですが、ビュー、モデル、コントローラの順番でいきます。

13.Adminビューの作成

app/resources/viewの下にadminディレクトリを作成し、
admin以下にlogin.blade.phpとhome.blade.phpを作成。
login.blade.phpはログイン画面、home.blade.phpはログイン後の画面として用意。
実際ログイン後は、home.blade.phpだけでなく、様々なビューができあがることになる。

どちらもview直下の(一般ユーザ用)login.blade.php、home.blade.phpをコピーすればOK。
Admin側と分かるように、文言等を少し変えておくとよい。

変更しなければいけない点はログイン画面のformタグのaction。
「action=”{{ url(‘/admin/login’) }}”」
としておく。
これでビューの準備はOK。

14.Adminモデルの作成

$ php artisan make:model Admin

adminsテーブルはusersテーブルと同構造なので、AdminモデルもUserモデルをコピペで。
クラス名をAdminにすることを忘れずに。

15.AdminAuthとAdminHomeコントローラの作成

ユーザ側のルーティングでは、「ログイン画面」や「ログイン処理」は「Auth/AuthController」にルートが切られている。
これを参考に、Admin用にAdminAuthControllerを用意していく。
$ php artisan make:controller AdminAuthController

中身は基本的にAuthControllerをコピペでOK。変えておくポイントは以下2点。

protected $redirectTo = '/admin/home'; //←書き換え
protected $loginView = 'admin.login';  //←追加

redirectToはログイン後にリダイレクトするパスを指定。
loginViewはログインページのView指定。これを指定しておかないとユーザ側のloginビューが表示されてしまう。

ユーザ側のルーティングでは、「ログイン後の画面」は「Auth/HomeController」にルートが切られている。
これを参考に、Admin用にAdminHomeControllerを用意していく。
$ php artisan make:controller AdminAuthController

中身は基本的にHomeControllerをコピペでOK。変えておくポイントは以下1点。

    public function index()
    {
        return view('admin.home'); //←表示Viewをhomeからadmin.homeへ変更。
    }

※上述のroutes.phpの設定でMiddlewareを指定しない場合は、コントローラ側のコンストラクタに指定をする。
【AdminAuthController.php】

    public function __construct()
    {
        $this->middleware('guest:webadmin', ['except' => 'logout']);
    }

【AdminHomeController.php】

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

これでコントローラの準備がOK。

16.表示確認

ざっと表示確認を行う。
以下のような感じでしょうか。
http://[Your-Laravel-Root-Domain]/loginで正しくログイン

http://[Your-Laravel-Root-Domain]/homeへ遷移(一般ユーザでログインできることを確認)

http://[Your-Laravel-Root-Domain]/admin/homeを表示

ログインできない。/admin/loginへ移動(一般ユーザログインでは管理ページは見れないことを確認)

http://[Your-Laravel-Root-Domain]/admin/loginで正しくログイン

http://[Your-Laravel-Root-Domain]/admin/homeへ遷移(管理ユーザでログインすれば管理ページは見られることを確認)

http://[Your-Laravel-Root-Domain]/admin/logoutを実行

http://[Your-Laravel-Root-Domain]/admin/homeを表示

ログインできない。/admin/loginへ移動(管理ユーザでログアウトすると、管理ページは見れなくなることを確認)

本日はここまで。

まとめ:Laravel5.2のMulti認証サンプル作成結果

ソースを読み込んでいくためにはPHPの「トレイト」を理解する必要があったり、LaravelのMiddlewareやFacadeといった考え方も理解している必要があります。ですので、非常に勉強になる内容だと思います。ロールでの切り分けサンプルも作成してみたいと思います。

WEBアプリケーション関連 人気連載リンク

基礎からPHPWEBアプリ解発を学ぶなら・・
PHP基礎 連載

より実践的なWEBアプリ開発講座!Bootstrap活用を学ぶなら・・
魁!小野の塾 連載

Recent News

Recent Tips

Tag Search