LoginSignup
38
40

More than 5 years have passed since last update.

Laravel5.1でMulti Auth(Kbwebs/MultiAuth編)

Last updated at Posted at 2015-07-28

追記

Laravel5.2に正式にMulti−Authに対応しました。なので、この記事はもう役割終了です。
こちらをどうぞ。


私にとってLaravelの最大の難所は、Multi Authです。つまり、標準ではusersテーブルのみで行われる認証を、users(一般ユーザー)、admins(管理者)に分けた認証です。

極力自力作成派なので、

を過去にトライしてみたのですが、毎日の実装の中で気楽に利用できるレベルではないと感じました。そこで、頼りたいのが、サードパーティー製のパッケージ?なのですが、なかなかこれというものがありません。

Multi Authパッケージの現状(2015年7月27日時点)

私の知る限り、4.2までは、ollieread/multiauthというのが主流だったようなのですが、5.xに対応しておらず、いくつかのフォークが存在するも、password_resetは動かないとか、いろいろと制限があるようです。

そのような中、5.1対応をうたう真新しいパッケージを発見!

パスワードリセットへの対応もしているようです。

Authを中心に動かしてみたのでやりかたをメモしておきます。

Kbwebs/MultiAuthを試す:準備

流れとしては次のような感じ

  • Kbwebs/MultiAuthを設置
  • 一般ユーザー用のテーブルとしてはusersテーブル(既存migrationファイル)を使う。
  • モデルとしてはUserを使う。
  • 管理者用テーブルとしてadminsテーブルを作る。但し、内容はusersと同じ。
  • モデルとしてはAdminを使う(新規作成)。
  • Seederでusers, adminsにユーザーを追加
  • 各種認証を試す。

Kbwebs/MultiAuthを設置する

基本は、本家のサイトのインストール手順通りに行う。

ファイルの取得

composer.jsonを編集。

"require": {
    "kbwebs/multiauth": "dev-master"
}

update。

composer update

使えるようにする(Auth機能)

config/app.phpのAuthServiceProviderの差し替える。

Illuminate\Auth\AuthServiceProvider::class

Kbwebs\MultiAuth\AuthServiceProvider::class

使えるようにする(PasswordReset機能:使う場合)

Illuminate\Auth\Passwords\PasswordResetServiceProvider::class

Kbwebs\MultiAuth\PasswordResets\PasswordResetServiceProvider::class

config/auth.phpの書き換え

'multi-auth' => [
    'admin' => [
        'driver' => 'eloquent',
        'model'  => App\Admin::class
    ],
    'user' => [
        'driver' => 'eloquent',
        'model'  => App\User::class
    ]
]

注意点としては、App\Admin::classを''で囲わないこと。

eloquentではなく、databaseを利用する場合は、

'multi-auth' => [
    'admin' => [
        'driver' => 'database',
        'table' => 'admins'
    ],
    'user' => [
        'driver' => 'database',
        'table' => 'users'
    ]
],

とする。

また、パスワードリセットを使う場合は、

'password' => [
    'email' => 'emails.users.password',
    'table' => 'password_resets',
    'expire' => 60,
],

とする必要があるようだ(emailにusersを追加)。

usersテーブルを作る

既にあるmigrateファイルをそのまま利用し、migrateする。

Userモデルを作る

既にあるApp\Userを使う。

adminsテーブルを作る

php artisan make:migration create_admins_table --create=admins

として、migrateのひな形を作り、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();
        });
    }

    public function down()
    {
        Schema::drop('admins');
    }
}

Adminモデルを作る

モデルは、Userをリネームして、Admin.phpを生成し必要な箇所を変更するか、artisanコマンドでひな形を生成し、Userを参考に編集します。

php artisan make:model Admin

実際の内容は、下記の通りですが、PasswordReset系のuseをKbwebsのものに変更しています。
逆にUserの方も、PasswordResetは(必要なら)変更します。

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
//use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
//use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

use Kbwebs\MultiAuth\PasswordResets\CanResetPassword;
use Kbwebs\MultiAuth\PasswordResets\Contracts\CanResetPassword as CanResetPasswordContract;



class Admin extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    use Authenticatable,CanResetPassword;

    protected $table = 'admins';
    protected $fillable = ['name', 'email', 'password'];
    protected $hidden = ['password', 'remember_token'];
}

元々のパスワードリセット系はコメントアウトし、Kbwebsのものを追加。
クラス名と、テーブル名はもちろん適切に変更する。
なお、上記コードは余計な?コメントを消去しています。

Seederでユーザーを登録

テスト用にユーザーを登録します。ここではSeederを使ってみます。
Laravel5.1から、Seederのひな形も作れるようになりました。

php artisan make:seeder UserTableSeeder
php artisan make:seeder AdminTableSeeder

UserTableSeederはこんな感じ。

<?php

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

class UserTableSeeder extends Seeder
{

    public function run()
    {
        //delete
        User::truncate();

        //Insert
        User::insert([
            [
                'name' => 'user1',
                'email' => 'user1@test.com',
                'password' => Hash::make('user1')
            ]
        ]);
    }
}

AdminTableSeederはこんな感じ。

<?php

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

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

        //Insert
        Admin::insert([
            'name' => 'admin1',
            'email' => 'admin1@test.com',
            'password' => Hash::make('admin1')
        ]);
    }
}

artisan db:seedコマンドでの実行対象となるよう、DatabaseSeeder.phpを編集します。

<?php

use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        Model::unguard();

        $this->call(UserTableSeeder::class);
        $this->call(AdminTableSeeder::class);

        Model::reguard();
    }
}

で、実行します。

php artisan db:seed

データが生成されます。※現状の記述ではModelに問題があり、エラーが発生します(調査中)。

Kbwebs/MultiAuthを試す:利用

利用は、

Auth::admin()->attempt(['email'=>'admin1@test.com','password'=>'admin1']);
Auth::user()->attempt(['email'=>'user1@test.com','password'=>'user1']);

という感じになります。

実際には、Middleware等を設定して利用することになるでしょう。

Middlewareの設定例

ここでは、admin認証用とuser認証用のMiddlewareを作ってみたいと思います。まずは、ひな形。

php artisan make:middleware AdminAuthenticate
php artisan make:middleware UserAuthenticate

AdminAuthenticateは、

<?php

namespace App\Http\Middleware;

use Closure;

class AdminAuthenticate
{
    public function handle($request, Closure $next)
    {
        if(\Auth::admin()->check())
        {
            //do nothing
        }
        else
        {
            return "go to admin login page.";
        }

        return $next($request);
    }
}

とりあえずこんな感じ。adminとしてログインしてればスルー。して無ければ、loginメッセージを出します(実際にはログインページへのリダイレクトとかになると思います)。

UserAuthenticateは、

<?php

namespace App\Http\Middleware;

use Closure;

class UserAuthenticate
{
    public function handle($request, Closure $next)
    {
        if(\Auth::user()->check())
        {
            //do nothing
        }
        else
        {
            return "go to user login page.";
        }

        return $next($request);
    }
}

基本、admin認証と同じ理屈。
Middlewareをルートで利用するためには、Kernel.phpに登録します(以下、抜粋)。

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'admin' => \App\Http\Middleware\AdminAuthenticate::class,
    'user' => \App\Http\Middleware\UserAuthenticate::class,
];

利用してみる

ここでは、route.phpだけの記述でlogin,認証,logout等が正しく動くがチェックしてみます。

//admin

Route::get('admin/login',function(){
    Auth::admin()->attempt(['email'=>'admin1@test.com','password'=>'admin1']);
    return Auth::admin()->get()->email;
});

Route::get('admin/logout',function(){
    Auth::admin()->logout();
    return "admin logout";
});

Route::get('admin',['middleware'=>'admin',function(){
    return "admin page";
}]);

//user

Route::get('user/login',function(){
    Auth::user()->attempt(['email'=>'user1@test.com','password'=>'user1']);
    return Auth::user()->get()->email;
});

Route::get('user/logout',function(){
    Auth::user()->logout();
    return "user logout";
});

Route::get('user',['middleware'=>'user',function(){
    return "user page";
}]);

なお、prefixを使って、下記の様に書くこともできる。

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

    Route::get('/',function(){
        return "admin page";
    });

    Route::get('login',function(){
        Auth::admin()->attempt(['email'=>'admin1@test.com','password'=>'admin1']);
        return Auth::admin()->get()->email;
    });

});

上記をroute.phpに設定したら、下記テストを行います。

  • adminページにアクセスしてみる。login促しメッセーがでれば、正しく「拒否されている」。
  • admin/loginにアクセスし、ログイン。ユーザー名が正しく取得できていればログイン完了。
  • 再びadminにアクセスし、"admin page"が表示されていれば、認証されている。
  • admin/logoutにアクセスし、ログアウトする。
  • 再びadminにアクセスし、login促しメッセージが表示されればOK。

  • userにおいても、上記と同じテストを行う。

  • userにログイン状態で、adminにアクセスするとどうなるか試してみる。

  • adminにログイン状態でuserにアクセスするとどうなるか試してみる。

注意

adminとuserのログインは同時に行うことが可能なので、テストの際は、気をつける。

パスワードリセット

私は、標準のパスワードリセットをあまり使わないので、いろいろ端折りましたが、本家サイトにパスワードリセットを使う場合の注意書きがまとまっています。

主な留意点としては、

  • Modelにkbwebsの機能をuseする。
  • config/auth.phpで'email' => 'emails.users.password'とする。
  • パスワードリセット用テーブルは独自のものを生成する。

専用のリセットテーブルは、下記のコマンドで、

php artisan kbwebs:multi-auth:create-resets-table
php artisan kbwebs:multi-auth:clear-resets

マイグレーションファイルの生成、全パスワードリセットができるみたいです。なお、Kbwebs独自のartisanコマンドを利用するには、ProviderにKbwebs\MultiAuth\PasswordResets\PasswordResetServiceProvider::classの追加が必要です。

38
40
1

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
38
40