search
LoginSignup
86
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

祝:Laravelが5.2で"MultiAuth"に対応!

Laravelは素晴らしいフレームワークです。ほとんど文句はありません。が、唯一の不満がMulti-Authに標準で対応していなかったことです。が、とうとう対応したようなので使ってみます。

ここでいうMulti-Authとは、認証用のユーザーテーブルとしてusersとadminsと別のテーブルを利用するようなものを意味しています。

これで、今までの苦労も報われます。

準備

では、認証に使うテーブルを作成するためのmigrateファイルや初期ユーザー登録用のseeder等を作成してみます。作成するものは、

  • テーブル(migrateすることにより作成します)
  • モデル(driverとしてeloquentを利用するので作成します)
  • 初期ユーザー(seederで登録してみます)

usersテーブル

migrateファイル

usersテーブル生成用のmigrateファイルは既に、database/migrationsの中に存在していますので、それをそのまま利用します。

モデル

usersテーブルと紐づくUserモデルは既にapp/User.phpとして存在していますので、それをそのまま利用します。

UserTableSeeder

usersテーブルにテスト用の初期ユーザーを登録するためのseederを用意します。

php artisan make:seeder UserTableSeeder

とすると、database/seeds以下にUserTableSeeder.phpが生成されますので、それを下記のようにします。

<?php

use Illuminate\Database\Seeder;
use App\User;

class UserTableSeeder extends Seeder
{

    public function run()
    {
        //削除
        User::truncate();

        //User生成
        $user = new User;

        $user->name = "user1";
        $user->email = "user1@user.com";
        $user->password = Hash::make('user1');

        //保存
        $user->save();
    }
}

adminsテーブル

続いてadminsテーブルの準備をしていきます。

migrateファイル

usersとは違い、adminsテーブル用のmigrateファイルはないので生成します。雛形は、

php artisan make:migration create_admins_table --create=admins

とすることで、生成されます。後は、users用のmigrateファイルを参考にして、下記のようにします。

<?php

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

class CreateAdminsTable extends Migration
{

    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();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('admins');
    }
}

モデル

モデルを生成します。雛型は、

php artisan make:model Admin

とすることで生成可能です。
User.phpと同じにしてもいいですが、ここでは継承するクラスだけModelからAuthenticatableに変えて置きます。

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    //
}

AdminTableSeeder

seederを用意します。

<?php

use Illuminate\Database\Seeder;
use App\Admin;

class AdminTableSeeder extends Seeder
{
    public function run()
    {
        //削除
        Admin::truncate();

        //Admin生成
        $admin = new Admin;

        $admin->name = "admin1";
        $admin->email = "admin1@admin.com";
        $admin->password = Hash::make('admin1');

        //保存
        $admin->save();
    }
}

migrateファイルとseederの準備ができたのでテーブルを作成し、初期データを登録します。

Migrate

php artisan migrate

Seeder

php artisan db:seed

これで準備ができました。

利用してみる

auth.phpの編集

基本的には、providersとguardsをいじれば大丈夫です。
パスワードリセットを使うのならpasswordsも設定しておきます。

<?php

return [


    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],


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

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
        //追加
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        //追加 for admin
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        //追加 for admin
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],
    ],


    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        //追加 for admin
        'admin' => [
            'provider' => 'admins',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

動作確認(とりあえず)

毎度の手抜きで、とりあえずroute.phpに記述して動作確認をしてみます。
本当はMiddleware等で実装すべきです(暇な時に追記します。雑なものでよければをこっちに書いてます)。

Route::get('admin',function(){

    //Guardを選択(admin)
    $auth = Auth::guard('admin');

    //認証
    if($auth->attempt(['email'=>'admin@admin.com','password'=>'admin1']))
    {
        echo "You are Admin!";
    }else{
        echo "You are not Admin!";
    }

    return;

});

Route::get('user',function(){

    //Guardを選択(user)
    $auth = Auth::guard('user');

    //認証
    if($auth->attempt(['email'=>'user1@user.com','password'=>'user1']))
    {
        echo "You are User!";
    }else{
        echo "You are not User!";
    }

    return;

});

動きました。
Multi-Authが本家に実装されたことで、少しはぐっすり眠れるようになります(追記:ぐっすり眠れませんでした、下記動作確認2をご覧下さい)。

動作確認2(重要)

メソッド間で認証情報が保持されず???という感じでしたが、Laravel5.2から、認証を含むSessionの保持(やCSRF,Cookie等)の処理ポリシーが変わったようで、webミドルウエアを通す必要があるようです。route.phpに新しくgroupが追加されていたので???と思っていましたが、このためのようです。

なので、下記のソースでは、/adminで取得した認証は、/hogeに共有されません。

Route::get('admin',function(){

    if(Auth::guard('admin')->attempt(['email'=>'admin1@admin.com','password'=>'admin1']))
    {
        return redirect('hoge');

    }else{

        return "You are not admin.";

    }

});

Route::get('hoge',function(){

    return Auth::guard('admin')->user()->name;

});

認証やSession状態を共有するためには、下記の様に、webミドルウエアを適用する必要があるようです。

Route::group(['middleware' => ['web']], function () {

    //
    Route::get('admin',function(){

        if(Auth::guard('admin')->attempt(['email'=>'admin1@admin.com','password'=>'admin1']))
        {
            return redirect('hoge');

        }else{

            return "You are not admin.";

        }

    });

    Route::get('hoge',function(){

        return Auth::guard('admin')->user()->name;

    });
});

ここに書いてありました。

動作確認3

ログインした後のページは、adminしかアクセスさせない場合、authミドルウエアにguardを指定すればOK


class AdminController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:admin', ['except' => 'index']);
    }

}

guardが指定されない場合は、auth.phpで設定された値が使用されます。

'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
],

メモ

5.2からroute.phpに、

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| This route group applies the "web" middleware group to every route
| it contains. The "web" middleware group is defined in your HTTP
| kernel and includes session state, CSRF protection, and more.
|
*/

Route::group(['middleware' => ['web']], function () {

});

という記述が追加されています。HTTP系の処理は基本、webミドルウエアをかませるほうがいいようです。

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
What you can do with signing up
86
Help us understand the problem. What are the problem?