Laravelで「Simple ACL」を構築する方法
Laravelの認証システムは、ユーザー登録、ログイン、ログアウト、パスワードリセットなどを簡素化し、ウェブアプリケーションに迅速かつ容易に実装できるソリューションを提供します。
ただし、ウェブサイトの一部へのアクセス権を制御したい場合、管理者以外のユーザーに特定のページの機能を無効化したい場合、または誰かが自分の連絡先のみを編集できるようにしたい場合には、LaravelのACL(アクセス制御リスト)を実装する必要があります(Laravel 5.1.11以降)。
ACLを構築するために、Laravelに組み込まれているGateクラスを使用します。このクラスは、ユーザー(ログインしているユーザーや特定のユーザー)が何かを「許可されているか」を確認するためのものです。以下にサンプルコードを示します:
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
上記のコードをコントローラに追加し、ログインしているユーザーがupdate-contactの権限を拒否されたかどうかを確認できます。また、反対の動作を行いたい場合は、Gate::allows
を使用できます。
LaravelのACLは、「Ability」という概念に基づいています。1つのAbilityは1つのキーです(例:update-contact)。
ACLのためのAbilityの定義
Abilityを定義するために、デフォルトではAuthServiceProviderに記述します。
class AuthServiceProvider extends ServiceProvider
{
public function boot(GateContract $gate)
{
parent::registerPolicies($gate);
$gate->define('update-contact', function ($user, $contact) {
return $user->id === $contact->user_id;
});
}
}
そして、以下のように確認できます:
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
Policiesの使用
AuthServiceProviderに直接多くの定義を書く代わりに、複数のPolicyクラスを作成して管理することができます。
以下のコマンドを実行すると、ContactPolicyというポリシークラスが自動的にapp/Policiesフォルダに作成されます:
php artisan make:policy ContactPolicy
これにより、ContactPolicyファイルが生成され、以下の内容が自動で作成されます:
<?php
namespace App\Policies;
class ContactPolicy
{
/**
* Create a new policy instance.
*
* @return void
*/
public function __construct()
{
//
}
// updateメソッドを追加
public function update($user, $contact)
{
return $user->id === $contact->user_id;
}
}
次に、このクラスをAuthServiceProvider
に登録します:
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Contact::class => ContactPolicy::class,
];
}
これで、コントローラで以下のように確認できます:
if (Gate::denies('update', $contact)) {
abort(403);
}