はじめに
Laravelには認可機能を簡単に実装出来るGateという機能が用意されているので使ってみました。
やる事
よくあるユースケースとして、ユーザー毎に画面の閲覧権限とPOST権限を作ってみたいと思います。
デフォルトで用意されているusersテーブルにint型でroleというカラムを追加して、
1: ディレクター 2: マネージャー 3: スタッフ
の形で実装したいと思います。
Gate
登録
AuthServiceProvider.php
にGateファサードを利用して以下の様に認可機能の登録します。
Gateにはconfig/auth.phpで指定している認証用のモデル(デフォルトはUserモデル)がフレームワークによって常に渡されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public function boot() { $this->registerPolicies(); // 第一引数には、abilityと呼ばれる認可種類名を渡す // クロージャには、認証しているユーザーモデルが渡される Gate::define('view', function ($user) { // roleカラムがデレクター or マネージャーの場合認可 return (in_array($user->role, [RoleEnum::DIRECTOR->value, RoleEnum::MANAGER->value])); }); Gate::define('approve', function ($user) { // roleカラムがディレクターの場合認可 return ($user->role == RoleEnum::DIRECTOR->value); }); } |
roleの値は分かりやすくEnumで表現してます。
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace App\Enums; enum RoleEnum: int { case DIRECTOR = 1; case MANAGER = 2; case STAFF = 3; } |
利用
Controllerで閲覧とPOSTメソッド時に登録したGateを利用してログインユーザーの認可を行います。
認可には、Gateファサードの
allows
メソッドの中で登録したability名を引数に渡します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class GateController extends Controller { public function index(Request $request) { // ディレクター or マネージャーの場合認可 if (!Gate::allows('view')) { abort(403); } return Inertia::render('Gate/Index'); } public function post(Request $request) { // ディレクターの場合のみ認可 if (!Gate::allows('approve')) { abort(403); } return Inertia::render('Gate/Index', [ 'postResult' => true ]); } } |
この状態で、ディレクター権限を持つユーザーでログインすれば画面表示から承認まで行う事が出来ますが、マネージャー権限のユーザーでは画面表示まで、スタッフ権限のユーザー何も出来ず403が返されます。
Policy
上記例では権限設定を2つしか設定していませんが多くの権限を設定する場合には、権限管理を行うPolicy機能を利用する事が出来ます。
Policyファイルを作成します。
php artisan make:policy ApprovalPolicy
次に各権限の設定を書きます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class ApprovalPolicy { use HandlesAuthorization; // 閲覧権限 public function view(User $user) { // roleカラムがディレクター or マネージャーの場合認可 return in_array($user->role, [RoleEnum::DIRECTOR->value, RoleEnum::MANAGER->value]); } // 承認権限 public function approve(User $user) { // roleカラムがディレクターの場合認可 return $user->role == RoleEnum::DIRECTOR->value; } } |
作成したApprovalPolicyを利用して
AuthServiceProvider.php
で以下の様にスッキリとGateを登録する事が出来ます。
1 2 3 4 5 6 7 | public function boot() { $this->registerPolicies(); Gate::define('view', [ApprovalPolicy::class, 'view']); Gate::define('approve', [ApprovalPolicy::class, 'approve']); } |
ミドルウェアでの使用
ControllerではなくMiddlerWareでGateの設定をする事も可能です。
デフォルト実装されている
Illuminate\Auth\Middleware\Authorize
が
App\Http\Kernel
クラスで
can
キーに割当されています。その為、ルーティングで以下の様に書くと、ControllerにGate::allowsを書かなくても同じ結果が得られます。
1 2 3 4 | Route::prefix('gate')->name('gate.')->group(function () { Route::get('/', [GateController::class, 'index'])->name('index')->middleware('can:view'); // ディレクター or マネージャーのみ Route::post('/approve', [GateController::class, 'approve'])->name('approve')->middleware('can:approve'); // ディレクターのみ }); |
さいごに
Gate機能を利用する事で簡単に認可機能を実装する事が出来ます。認可機能を実装する際には利用してみたいと思います。