Laravel5.3におけるマルチユーザーログインの実装方法(Laravel5.4でも動作確認)

概要

Laravelの認証機能は、ガード(guards)とプロバイダ(providers)の2つのコンポーネントで構成されています。ガードは各リクエストにおいてユーザーがどのように認証されるかを定義し、例えばセッションガードはセッションストレージの状態を維持し、クッキーおよびトークンガードはAPIトークン付きのリクエストでの認証を処理します。プロバイダは永続化されたストレージからユーザー情報を取得する方法を定義します。LaravelではEloquentとデータベースクエリビルダーの2つの方法がサポートされており、必要に応じてカスタムプロバイダを追加することも可能です。

Laravel5.2と比較して、Laravel5.3では内部コードが大幅に変更され、メソッドがより簡潔になっています。コードの変更はありますが、基本的な仕組みは同じであり、異なるメソッドをオーバーライドすることで実現できます。

標準認証の設定

まず、Laravel 5.3に付属の認証機能を使用します:

php artisan make:auth

このArtisanコマンドにより、ユーザー認証に必要なルート、ビュー、HomeControllerが生成されます。認証ルートも同時に作成され、routes/web.phpファイルを確認すると、以下のように更新されていることがわかります:

Auth::routes();

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

Auth::routes()はログイン、登録、パスワードリセットのルートを定義し、/homeは認証成功後のリダイレクト先です。

動作確認

それではフロントエンドユーザーのログインを実装します。これはLaravelのデフォルトのUsersテーブルによるログインです。生成されたデフォルトの認証機能によりすべてのコードは既に記述されており、あとはマイグレーションコマンドを使って認証関連テーブルを作成するだけです:

php artisan migrate

このコマンド実行後、usersテーブルとpassword_resetsテーブルが作成され、それぞれユーザー情報とパスワードリセット情報を格納します。その後、ブラウザでhttp://blog.me/registerにアクセスして新しいユーザーを登録できます。

iwanliというユーザーを作成し、登録成功後に自動的に/homeページに遷移し、登録したユーザー名が表示されます。ログインやパスワードリセット機能も既に実装されているため、詳細なテストは省略します。

カスタムユーザーテーブルでのログイン

まずデフォルトの認証設定ファイルauth.phpを見てみましょう。設定内容は以下の通りです:

<?php
return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
           'expire' => 60,
        ],
    ],
];

認証はガードとプロバイダの2つで構成され(認証ドキュメント参照)、defaults設定はどのガード認証ドライバを使用するかを指定します。この設定にadminadminsのオプションを追加します。

<?php
return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
           'expire' => 60,
        ],
    ],
];

管理者ユーザー用テーブルとモデルの作成

次に管理者ユーザーのログインを実装します。以下のArtisanコマンドを使用して管理者モデルを生成します:

php artisan make:model Models/Admin -m

-mオプションを付けることで対応するマイグレーションファイル*_create_admins_tableが生成されます。このデータベーステーブルのフィールドをusersテーブルと同じように定義します:

<?php

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

class CreateAdminsTable extends Migration
{
    /**
     * マイグレーションを実行する。
     *
     * @return void
     */
    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * マイグレーションを元に戻す。
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

管理画面ではログイン機能のみが必要なため、adminsテーブルにいくつかのデータを挿入します:

php artisan make:seeder AdminsTableSeeder

コマンド実行後、database/seedsディレクトリにAdminsTableSeeder.phpファイルが生成されます。次にデータモデルファクトリを定義し、database/factories/ModelFactory.phpに以下のコードを追加します:

<?php

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/

$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

$factory->define(App\Models\Admin::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

モデルファクトリが定義された後、AdminsTableSeeder.phpでデータを挿入します:

<?php

use Illuminate\Database\Seeder;

class AdminsTableSeeder extends Seeder
{
    /**
     * データベースシードを実行する。
     *
     * @return void
     */
    public function run()
    {
        factory('App\Models\Admin',3)->create([
            'password' => bcrypt('123456')
            ]);
    }
}

データの挿入準備ができたら、DatabaseSeeder.phpAdminsTableSeederクラスを追加します:

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * データベースシードを実行する。
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(AdminsTableSeeder::class);
    }
}

最後にマイグレーションコマンドを実行します:

php artisan migrate --seed

これでデータベースを確認できます。

Adminモデルクラスの修正

<?php

namespace App\Models;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    use Notifiable;

    /**
     * 代入可能な属性。
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * 配列から隠すべき属性。
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

管理者認証ルートとコントローラーの作成

Artisanコマンドでコントローラーを生成します:

php artisan make:controller Admin/LoginController 
php artisan make:controller Admin/DashboardController

Admin/LoginController.phpを編集します。コードは以下の通りです:

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * ログイン/登録後のリダイレクト先。
     *
     * @var string
     */
    protected $redirectTo = '/admin/dash';
    protected $username;

    /**
     * 新しいコントローラーインスタンスを生成する。
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest:admin', ['except' => 'logout']);
        $this->username = config('admin.global.username');
    }
    /**
     * ログインフォームを表示
     * @author 晚黎
     * @date   2016-09-05T23:06:16+0800
     * @return [type]                   [description]
     */
    public function showLoginForm()
    {
        return view('admin.login.index');
    }
    /**
     * 認証ドライバのカスタマイズ
     * @author 晚黎
     * @date   2016-09-05T23:53:07+0800
     * @return [type]                   [description]
     */
    protected function guard()
    {
        return auth()->guard('admin');
    }
}

LoginControllerのコンストラクタでguestミドルウェアを修正し、異なるルートにリダイレクトするようにします:

  • app\Http\Middleware\RedirectIfAuthenticated.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * 入力リクエストを処理する。
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            // ガードによって異なるページにリダイレクト
            $url = $guard ? 'admin/dash':'/home';
            return redirect($url);
        }

        return $next($request);
    }
}

Admin/DashboardController.phpを編集します。コードは以下の通りです:

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class DashboardController extends Controller
{
    /**
     * 新しいコントローラーインスタンスを生成する。
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth.admin:admin');
    }

    /**
     * アプリケーションダッシュボードを表示する。
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        dd('管理者ホーム、現在のユーザー名:'.auth('admin')->user()->name);
    }
}

DashboardControllerのコンストラクタにauth.adminミドルウェアを追加しました。これはカスタムミドルウェアなので、新たに作成します:

php artisan make:middleware AdminAuthMiddleware

AdminAuthMiddlewareを編集します:

<?php

namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminAuthMiddleware
{
    /**
     * 入力リクエストを処理する。
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next,$guard = null)
    {
        if (Auth::guard($guard)->guest()) {
            if ($request->ajax() || $request->wantsJson()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('admin/login');
            }
        }
        return $next($request);
    }
}

app\Http\Kernel.phpで登録します:

protected $routeMiddleware = [
    ......
    'auth.admin' => \App\Http\Middleware\AdminAuthMiddleware::class,
    ......
];

routes/web.phpに以下のルートを追加します:

Route::group(['prefix' => 'admin','namespace' => 'Admin'],function ($router)
{
    $router->get('login', 'LoginController@showLoginForm')->name('admin.login');
    $router->post('login', 'LoginController@login');
    $router->post('logout', 'LoginController@logout');

    $router->get('dash', 'DashboardController@index');
});

ビューの作成と修正

最後に管理者認証用のビューを作成します。既存のユーザー認証テンプレートをコピーして適宜修正するだけで済みます。resources\views\auth\login.blade.phpresources\views\admin\login\index.blade.phpとしてコピーします。

resources\views\admin\login\index.blade.php内のログイン・登録フォームの送信先を変更します:

{{ url('/login') }} -> {{ route('admin.login') }}

ブラウザでhttp://blog.me/admin/loginにアクセスしてテストします:

ログインボタンをクリックすると、http://blog.me/admin/dashに遷移し、管理者ログインが成功したことが確認できます。

以上でフロントとバックエンドのユーザー同時ログイン認証機能が完成しました。お楽しみください!

転載元:http://laravelacademy.org/post/5925.html

タグ: laravel 認証 セッション ユーザー管理 マルチユーザーログイン

5月28日 23:46 投稿