LaravelのGateによるユーザアクセス認可

Laravelではユーザ認証とは別にユーザに特定のルートにアクセスできる権限を与えたいとき、ルートへの認可としてGateを利用することができます。
今回はGateを利用して一部のユーザに管理者権限を与えて管理機能へのアクセスを許可する方法をまとめておきます。

開発環境

Laravel 6.6.0

Userモデルに権限カラムを追加

Userモデルに「is_admin」というBoolean型のカラムを追加します。

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

$ php artisan make:migration add_column_is_admin_to_users_table --table=users
<?php

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

class AddColumnIsAdminToUsersTable extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->boolean('is_admin')->default(false)->after('email');
        });
    }

    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('is_admin');
        });
    }
}

マイグレーション実行

$ php artisan migrate

Gateの設定

AuthServiceProviderクラスのbootメソッドに権限を定義します。
以下の設定ではusers.is_adminがTRUEのとき「admin」という権限が有効となります。

    public function boot()
    {
        $this->registerPolicies();

        // 以下を追加
        Gate::define('admin', function (\App\Models\User $user) {
            return $user->is_admin;
        });

    }

ルーティング設定

middleware(‘can:admin’)を設定することで「admin」権限だけがアクセスできるルートとなります。
以下の例では/user以下は一般ユーザ用、/admin以下は管理ユーザ用と分けることができます。

Route::middleware('verified')->group(function() {
    // 一般ユーザ用
    Route::prefix('user')->group(function(){
        Route::get('/', 'User\HomeController@index');
        ...
    });
    // 管理ユーザ用
    Route::prefix('admin')->middleware('can:admin')->group(function(){
        Route::get('/', 'Admin\HomeController@index');
        ...
    });
});

ログイン後のリダイレクト先

ログイン直後のページは一般ユーザとは異なるURLにリダイレクトさせたいですね。

LoginControllerはトレイト(use AuthenticatesUsers;)を使用してAuthenticatesUsersを継承しているのでAuthenticatesUsersのauthenticatedメソッドをオーバーライドして認証直後にリダイレクト先を設定することができます。

app/Http/Controllers/Auth/LoginController.phpに追記

    // Override
    protected function authenticated(\Illuminate\Http\Request $request, $user)
    {
        if ($user->is_admin) {
            // 管理ユーザ
            $this->redirectTo = '/admin';
        } else {
            // 一般ユーザ
            $this->redirectTo = '/user';
        }
    }

後記

ユーザ/管理者のテーブルを分ける必要がない場合はMulti-AuthにしなくともGateによる認可で簡単に実現できます。
また、今回はadminだけでしたが各ユーザにさまざまな権限を追加することも可能ですね。