はじめに
RBAC方式でアクセス制御をすることになったので、larave-permissionの概要を簡単にまとめていきます。
初心者の方向けに簡単に概要を把握できるように書いていきます。
laravel-permissionとは
Laravelのプラグインの1つで、RBAC方式などのアクセス制御を実現することができます。
RBAC方式とは
RBAC方式とは、「ある対象(例えばユーザー)」に「ロール(一般ユーザー・管理者など)」という概念が割当てられるようにしたものです。このロールに対して、「何ができるか」という権限が付与される方式のことです。
例えば、「勉強会の一般参加者はGUESTカードを渡され、運営側の人はSTAFFカードが渡される。STAFFカードを持っている人は特定の部屋に入ることができる。」というように特定のロールに、特定の行動許可が付与されるようなイメージです。
インストール&設定方法
larave-permissionはcomposer経由でインストールすることが可能です。
composer require spatie/laravel-permission
config/app.php
に下記1行を追加します。
'providers' => [
// ...
// 追記
Spatie\Permission\PermissionServiceProvider::class,
];
続いて、下記コマンドを実行します。artisan vendor:publishを実行すると、下記の設定ファイル(config/permission.php)と、マイグレーションファイルが作成されます。
- /config/permission.php
- /database/migrations/yyyy_mm_dd_hhmmss_create_permission_tables.php
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
キャッシュをクリアして、
php artisan optimize:clear
マイグレーションを実行します。
php artisan migrate
すると、以下のように5つの新規テーブルが作成されます。
最後に、User
モデルにSpatie\Permission\Traits\HasRoles
を追加すれば、初期の設定は完了です。
use Illuminate\Foundation\Auth\User as Authenticatable;
+ use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
+ use HasRoles;
// ...
}
ロールと権限の作成
まずは準備として、ユーザー、ロール、権限を作成し、それぞれを紐づけていきます。流れとしては以下の通り
-
山田太郎(管理者)
、山田花子(編集者)
というテストユーザーを作成する -
admin
、editor
というロールを作成する -
edit articles
、delete articles
という権限を作成する -
admin
ロールに対して、edit articles
、delete articles
権限を紐づける -
editor
ロールに対して、edit articles
権限を紐づける -
山田太郎(管理者)
ユーザーにadmin
ロールを割り当て、山田花子(編集者)
ユーザーにeditor
ロールを割り当てる
シーダーファイルとしては以下のようになります。
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RolesAndPermissionsSeeder extends Seeder
{
/**
* Run the database seeds.
* @return void
*/
public function run(): void
{
// adminユーザーを作成
$adminUser = new User();
$adminUser->name = '山田太郎(管理者)';
$adminUser->email = 'aaa@bbb.com';
$adminUser->password = Hash::make('password');
$adminUser->save();
// editorユーザーを作成
$editorUser = new User();
$editorUser->name = '山田花子(編集者)';
$editorUser->email = 'aaa@bbb.com';
$editorUser->password = Hash::make('password');
$editorUser->save();
// Roleの作成
$admin = Role::create(['name' => 'admin']);
$editor = Role::create(['name' => 'editor']);
// Permissionの作成
$permissionOfEditArticles = Permission::create(['name' => 'edit articles']);
$permissionOfDeleteArticles = Permission::create(['name' => 'delete articles']);
// RoleとPermissionを関連付け
$admin->givePermissionTo($permissionOfEditArticles);
$admin->givePermissionTo($permissionOfDeleteArticles);
$editor->givePermissionTo($permissionOfEditArticles);
// UserにRoleを割り当て
$adminUser->assignRole('admin');
$editorUser->assignRole('editor');
}
}
作成したシーダーファイルを実行して、準備は完了です。
php artisan db:seed --class=RolesAndPermissionsSeeder
アクセス制御を実装する3つのパターン
ここからは実際にアクセス制御をする際にどうのように実装すればいいのか?というところで、3つのパターンを例として説明していきます
結論、②のコントローラー内で実装することが個人的には多いですが、念のためRouter内で実装する①と、bladeで実装する③も記載します
①Router内で認可処理を実施する
まずは、Router内で処理を実施するために、Kernel.php
にミドルウェアとして登録します
protected $routeMiddleware = [
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'roleOrPermission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
これにより、ミドルウェアとして使用できるようになるので、ユースケースに合わせて下記のように実装していきます
// Roleによるチェック
Route::group(['middleware' => ['role:admin|editor']], function () {
// ・・・
});
// Permissionによるチェック
Route::group(['middleware' => ['permission:delete articles']], function () {
// ・・・
});
// Role or Permissionによるチェック
Route::group(['middleware' => ['roleOrPermission:editor|read']], function () {
// ・・・
});
②コントローラー内で認可処理を実施する
コントローラーで処理をするパターンです。個人的な感覚ではこちらのパターンで実装することが多いです
class TestController extends Controller
{
public function index(Request $request): JsonResponse
{
// 認証済みユーザーのロールが"admin"かどうかをチェック
if (!$request->user()->hasRole('admin')) {
abort(403, 'アクセスする権限がありません。');
}
// ・・・
③blade内で認可処理を実施する
基本SPA構成が多く、使わないけど念のため
@role('editor')
@endrole
@hasallroles('editor|admin')
@else
@endhasallroles
まとめ
以上でlarave-permissionを利用したロールベースアクセス制御の実装が完了です。今回初めて使用したので、何か気付いたところがあればコメントで教えていただけると嬉しい限りです