Webアプリでは、特定の機能を実行する権限があるかどうかをチェックするために「認可」という仕組みを利用します。
また、PHPのフレームワークであるLaravelでは、この「認可」を簡単に実装する仕組みとしてGate(ゲート)とPolicy(ポリシー)が用意されています。
この記事では、Laravel11で
Gate(ゲート)とPolicy(ポリシー)を利用して
「認可」機能を実装する方法
を解説していきます。
「認可」と類似したものに「認証」があります。
この2つの違いについても解説しますので、ぜひ参考にしていただけるとうれしいです!
- Gate(ゲート)とPolicy(ポリシー)を使用して「認可」機能を実装する方法
- 「認証」と「認可」の違い
- 「認可」機能のレスポンスをカスタマイズする方法
「認証」と「認可」の違い
まずは「認証」と「認可」の違いについて解説します。
認証 | 認可 |
---|---|
ユーザーの身元を確認すること | 特定のリソース(機能)へのアクセス権限があるかどうかを確認すること |
混同されがちですが、「認証」と「認可」には、このように役割に明確な違いがあります。
- 「認証」は、ユーザーの身元を確認して不正アクセスを防ぐための仕組み
- 「認可」は、「認証」によって身元確認が行われたユーザーに、特定の機能の利用権限があるかどうかをチェックする仕組み
「認可」については、管理者と閲覧者をイメージしていただくと理解しやすいかと思います。
管理者はあらゆる機能を実行する権限を持ちますが、閲覧者にはデータを見る権限しか無く、編集・削除といった機能は実行できません。
当記事でご紹介するGate(ゲート)やPolicy(ポリシー)は、「認可」を実装するための仕組みです!
ちなみに、Laravelでは「認証」機能を簡単に実装する方法として、Laravel Breezeなどの仕組み(パッケージ)が用意されています。
こちらも今後、別の記事で詳しくお伝えできればと考えています。
Gate(ゲート)とPolicy(ポリシー)の関係性
Laravelで「認可」を実装するには、Gate(ゲート)やPolicy(ポリシー)を利用します。
この2つは、いわばルーティングとコントローラと同じ関係性を持ちます。
※公式ドキュメントでもそのような説明があります。
具体的には、以下のように関係性が類似しています。
- ルーティング → Policy(ポリシー)には「認可」の判定用のメソッドを定義
- コントローラ → Gate(ゲート)にはPolicy(ポリシー)で定義したメソッドを呼び出すときの「名前」を定義
上記のイメージを持っていただくと、「認可」を実装するハードルもぐっと下がるので参考にしていただければと思います!
【手順】Gate(ゲート)とPolicy(ポリシー)の基本的な使い方
本章では具体的にゲートとポリシーを使用して「認可」を実装する手順を解説します。
前述したように、「認可」はそのユーザーに機能の使用権限があるかどうかをチェックする仕組みです。
したがって、「認可」を実装する際には、前提としてユーザー認証機能が実装されている必要があります。
当記事でもすでにユーザー認証機能が実装されている想定で解説を進めていきます。
なお、当記事では「TODOアプリのタスク編集権限」を例に解説を進めていきます。
それでは、各STEPを順番に見ていきましょう!
STEP1 Gate(ゲート)を定義する
Gate(ゲート)はApp/Providers/AppServiceProvider.php
のboot()
メソッドに定義します。
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::define('task-edit', [TaskPolicy::class, 'edit']);
}
このソースコードでは、STEP2で、Policy(ポリシー)で実装するedit()
メソッドの呼び出し名としてtask-edit
を定義しています。
STEP2 Policy(ポリシー)に「認可」の判断基準となる処理を記述する
Policy(ポリシー)ファイルはコマンドで作成することが可能です。
具体的には、以下のコマンドで作成します。
php artisan make:policy TaskPolicy
補足として、ポリシーメソッドのサンプルを含んだクラスを生成したい場合は、下記のように--model
オプションを付けます。
php artisan make:policy TaskPolicy --model=Task
続いて、生成されたTaskPolicy.php
に以下のソースコードを記述します。
public function edit(User $user, Task $task)
{
return $user->id === $task->user_id;
}
上記はGate(ゲート)で認可処理を行う際に使用するメソッドです。
現在ログイン中のユーザIDと編集対象のタスクのユーザID=タスク作成者が一致するかどうかを検証し、結果をreturnしています。
STEP3 「認可」を実行したい箇所にGate(ゲート)による処理を記述する
最後に、STEP1~STEP2で定義した「認可」機能によって権限チェックを行いたい箇所にGate(ゲート)による判定処理を記述します。
/**
* タスク編集ページを表示
*/
public function edit(Task $task)
{
// ゲートの基本的な記述
if (! Gate::allows('task-edit', $task)) {
abort(403);
}
// ~ 認可されたあとの処理 ~
}
上記のedit()
は、タスク編集ページを呼び出すためのメソッドです。
実際にタスク編集ページを呼び出す前に、Gate(ゲート)によって権限チェックを行っています。
Gate::allows(‘task-edit’, $task)の「task-edit」はApp/Providers/AppServiceProvider.php
のboot()
メソッドで定義した、Policy(ポリシー)メソッド呼び出し用の名前です。
また、abort()
メソッドに403を渡すことで、権限がないときには403エラーが返るようになります。
【補足】Gate(ゲート)の処理を簡単に書く
以上がGate(ゲート)の基本的な書き方ですが、もう少しシンプルに書く方法もあります。
/**
* タスク編集ページを表示
*/
public function edit(Task $task)
{
// ゲートの基本的な記述
// if (! Gate::allows('task-edit', $task)) {
// abort(403);
// }
// ゲート記述簡単化
Gate::authorize('task-edit', $task);
// ~ 認可されたあとの処理 ~
}
上記のようにGate::authorize('task-edit', $task);
とするだけで認可処理を実行できます。
エラーメッセージのカスタマイズ
この書き方の場合、エラーメッセージ部分は以下のようになります。
もしもエラーメッセージをカスタマイズしたい場合は、Policy(ポリシー)のメソッド内の処理を以下のように修正します。
エラーメッセージをカスタマイズ
use Illuminate\Auth\Access\Response; // 追加
public function edit(User $user, Task $task)
{
// 元々の処理
//return $user->id === $task->user_id;
// エラーメッセージカスタマイズ
return $user->id === $task->user_id
? Response::allow()
: Response::deny('タスクの編集権限がありません。');
}
HTTPレスポンスを任意のものにする
403エラーではなく、別のHTTPレスポンスを返したい場合は以下のように記述することも可能です。
HTTPレスポンスを任意のものにする
use Illuminate\Auth\Access\Response; // 追加
public function edit(User $user, Task $task)
{
// 元々の処理
//return $user->id === $task->user_id;
// エラーメッセージカスタマイズ
return $user->id === $task->user_id
? Response::allow()
: Response::denyWithStatus(404);
}
Gate(ゲート)によるレスポンスのカスタマイズについては他にも色々な仕組みが用意されています。
詳しくはLaravel11 公式ドキュメント(日本語)をご覧ください。
まとめ
以上がLaravel11で「認可」機能を実装する方法でした。
この記事でご紹介したのはGate(ゲート)やPolicy(ポリシー)の使い方の中でも最も基本的な内容です。
ただ、ここまでの内容を理解できていれば、あとは公式ドキュメントをご覧いただくことでご自身の状況に適したカスタマイズができるかと思います。
この記事が少しでもお役に立ったなら何よりです!
当ブログではLaravelやPHP、WordPressなどに関する情報を発信しています。
ご興味のある方はほかの記事もご覧いただけるとうれしいです。
それでは、最後までご覧いただきありがとうございました!
コメント