Laravelの認可機構GateとPolicyを紐解く
前書き
Laravelのフレームワークには認可に伴う機能として、Gate
とPolicy
が標準で提供されている。
この二つの機能は似ているようで異なる特徴を持っており、適切に使い分けることが重要である。
本記事では、Gate
とPolicy
の違いに焦点を当て、それぞれの特徴や適切な採用するシチュエーションについて解説する。
理解を助けるため、オフィスビルのセキュリティシステムを例として用いる。
Gateとは
まずは、Gate
について説明する。
名前が示すとおり、Gate
はオフィスビルの入口にある中央受付のようなものである。
すべての訪問者はこの受付を通過する必要があり、ビル全体への入館許可があるかどうかを判断される。
Gate
は技術的には、柔軟なクロージャーを使用して定義することができる権限チェックの仕組みである。
このアプローチは以下の場合に最適であると考える。
- アプリケーション全体に関わる一般的な権限チェック
- シンプルな条件に基づく判断
- モデルに特化していないグローバルなルール
Policyとは
次に、Policy
について説明する。
Policy
は各部屋や各フロアに配置された専用セキュリティシステムのようなものである。
ここで部屋やフロアはLaravelのモデル(データベースの各テーブルを表すクラス)に相当する。
特定の部屋やリソースへのアクセス権限があるかといった、より細かい粒度の判断を行う。
Policy
は特定のモデルに関連する権限チェックを行うためのクラスであり、各メソッドは特定の操作(例:作成、更新、削除)に対する権限を確認する。
- リソース(モデル)中心の設計
- メソッドごとにグループ化されたポリシー定義
- 特定のモデルに対するCRUD操作の権限管理
- 複雑な認可ロジックの実装
GateとPolicyの違い
両者の本質的な違いは適用範囲と責任にある。
Gate
は全体の入口(アプリケーション全体)の権限を管理し、Policy
は特定の部屋やフロア(特定のモデル)に対するアクセス権限を管理する。
具体的には、以下のような違いがある。
-
Gate
は特定のモデルに関連しない一般的な権限チェックを行う -
Policy
は特定のモデルに紐づいた権限チェックを行う
使用例
Gateの事例
私の経験では、RBAC(Role-Based Access Control:役割ベースのアクセス制御)のような、モデルに直接関連しない一般的な権限チェックにはGate
が効果的である。
例えば、管理者権限を持つユーザーかどうかを確認する場合、以下のようにGate
を使用することができる。
// AppServiceProviderなどで定義
Gate::define('is-admin', function (User $user) {
return $user->role === 'admin';
});
// 使用例
if (Gate::allows('is-admin')) {
// 管理者向けの処理
}
Policyの事例
一方、特定のモデルに対する操作権限の管理にはPolicy
が適している。
私の実装経験では、ユーザーが自分の投稿のみを編集できるようにするケースが典型的な例である。
class PostPolicy
{
// 更新権限のチェック
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
// 削除権限のチェック
public function delete(User $user, Post $post)
{
return $user->id === $post->user_id || $user->isAdmin();
}
}
// 使用例
if ($user->can('update', $post)) {
// 投稿更新処理
}
ハイブリッドアプローチ
Gate
とPolicy
は排他的なものではなく、むしろ互いを補完するものである。
実際のアプリケーションでは、両方を組み合わせた「ハイブリッド」に運用することができる。
例えば、以下のように組み合わせることができる。
// Gateで全体的な権限を定義
Gate::define('access-admin-panel', function (User $user) {
return $user->hasRole('admin') || $user->hasRole('editor');
});
// Policyで特定モデルへの操作権限を定義
class ArticlePolicy
{
public function create(User $user)
{
// Gateを利用しつつ、追加条件を設定
return Gate::allows('access-admin-panel', $user) && $user->emailVerified();
}
}
まとめ
Gate
とPolicy
は、Laravelの認可機能を実装するための強力かつ柔軟なツールである。
Gate
はアプリケーション全体の一般的な権限管理に適しており、Policy
は特定のモデルに対する詳細な権限制御に向いている。
適材適所で使い分け、あるいは組み合わせることで、セキュアで管理しやすい認可システムを構築できる。
実装する際は、アプリケーションの規模や要件に応じてアプローチを選択することが重要である。
Discussion