はじめに
Laravelでロールベースアクセス制御の割としっかりしたものを提供する必要があったので、
Laravelの拡張パッケージでお馴染みのSpatieが提供しているlaravel-permissionを試してみました。
何がどのように関係してくるのか毎回英語を読むのが怠いので残しておきます。
使ってるうちに知見が得られたら、なるべくここを更新します。
今のところは認可チェックする各ミドルウェアのテストコードを書いて動かして中身を理解したレベルです。
環境
PHP 7.2
Laravel 5.7
※動くことを確認した
インストール
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
テーブルがいくつか作られるので、モデルを理解しておく
rolesとpermissionsのguard_nameには、
config/auth.phpで設定しているデフォルトのguardが入る。
複数のguardを設定したい場合のガイドはあるけど、今回は必要ないので飛ばす。
model_typeにはEloquentのクラスが入る。
どうやらEloquentのポリモーフィックリレーションを使用して実装されていそうなことが判る。
(ソース見ると実際そうなってる)
テーブルについて
roles
概要
役割のマスタテーブル
予め必要なものを登録しておく
登録するものの例:
- admin
- operator
- customer
など
※Super-adminとか定義できるみたいなので、その辺も念頭に置いて設定する
登録方法
$role = \Spatie\Permission\Models\Role::create(['name' => 'operator']);
model_has_roles
概要
モデルに対して役割を紐づける
userモデルに付与すれば、それが管理者とか運用者とかになる
部長・課長とか付けて役職と紐づけても良いと思う
登録方法
$user->assignRole('operator', 'customer');
'operator'とかの箇所はrole_idでも可。
メソッドの中で、stringかnumericかチェックして検索条件を切り替えてる
解除方法
$user->removeRole('read');
permissions
概要
許可設定のマスタテーブル
予め必要なものを登録しておく
登録するものの例:
- read
- write
- delete
など
登録方法
$permission = \Spatie\Permission\Models\Permission::create(['name' => 'read']);
model_has_permissions
概要
モデルに対して直接許可設定を付与する
userモデルに付与すれば、特権ユーザーみたいなものが作れる想定
(普通は管理者以上が触れる機能だけど、事務員さんに実際は入れてもらうので管理者じゃなくても権限付与したい、とかそういうヤツ)
登録方法
$user->givePermissionTo('read', 'write');
'read'とかの箇所はpermission_idでも可。
メソッドの中で、stringかnumericかチェックして検索条件を切り替えてる
解除方法
$user->revokePermissionTo('read');
role_has_permissions
概要
役割に対して許可設定を紐づけておくマスタテーブル
登録方法
以下のどちらか
$role->givePermissionTo($permission);
// or
$permission->assignRole($role);
まとめて登録したい場合は以下のどちらか使うとぐるぐるしなくて良い
(中でぐるぐるはしてるけど)
$role->syncPermissions($permissions);
// or
$permission->syncRoles($roles);
解除方法
役割に対する許可の設定を動的に変えるのがあまりイメージは湧かないけど以下でできる
(誤ったデータで作った場合に消したいとかそれくらいかな~と)
$role->revokePermissionTo($permission);
// or
$permission->removeRole($role);
2019/01/23補足
各ミドルウェアの実装上は使われていない。
どんなときに使われるかチェックしたら、
「hasPermissionViaRoleでPermissionを渡すと、そのPermissionがRoleに存在するかチェックする」
だった。
Roleごとに細かい権限付与したい場合は必要だけど、
カジュアルに役割 or 権限でチェックかけたい場合には、
このテーブルを使う必要はないですね。
最初に何が必要か
以下のテーブルについて、システムの初期セットアップで必要
(メンテナンス画面作ってちまちま入れても良いけど)
- roles
- permissions
- role_has_permissions
マイグレーション実行する
テーブルのことが判ったところで、マイグレーション実行
php artisan migrate
この後はSeederとか使ってテキトーなデータを以下のテーブルに突っ込んでおく
- roles
- permissions
- role_has_permissions
使い方
ユーザー登録
(めんどくさいので割愛)
User::createして戻り値で取ったuserをassignRoleかgivePermissionToする
コードに入れる
middleware
middlewareに設定したいのでmiddleware使う
以下を足す
protected $routeMiddleware = [
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
上記の実装見れば判るけど、Laravelからすると特殊な構成の認証ユーザーの持ち方をしている場合は、
自前のクラスを作って差し替えれば、思い通りになる。
(実装自体は簡単過ぎるので書かない)
// rolesのデータでだけチェック
Route::group(['middleware' => ['role:admin|operator']], function () {
//
});
// permissionsのデータでだけチェック
Route::group(['middleware' => ['permission:read|write']], function () {
//
});
// roles or permissionsのデータに居るかをチェック
Route::group(['middleware' => ['role_or_permission:operator|read']], function () {
//
});
role_has_permissionってどこで使われるんだ??
blade
使わないけど残しておく
@role('operator')
@endrole
@hasallroles('writer|admin')
@else
@endhasallroles
permission周りは他のと同じで@can
を使うらしい
おわりに
大体理解した気がする。
業務システムに必要なところも実装されてそうだし良さげ。
今回の要件に合致すれば使おうかな。
技術的な課題としてはVueでどうやって連携させるかかなー。
メニュー周りくらい&SPAで書いてるわけじゃないから、bladeに直接vueコンポーネント書いて回避するようにする気がする。