LoginSignup
1
0

More than 1 year has passed since last update.

laravel-permissionを利用したロールベースアクセス制御(RBAC)を実装する

Last updated at Posted at 2023-01-12

はじめに

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行を追加します。

config/app.php
'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つの新規テーブルが作成されます。
image.png
最後に、UserモデルにSpatie\Permission\Traits\HasRolesを追加すれば、初期の設定は完了です。

App\Models\User.php
use Illuminate\Foundation\Auth\User as Authenticatable;
+ use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
+   use HasRoles;

    // ...
}

ロールと権限の作成

まずは準備として、ユーザー、ロール、権限を作成し、それぞれを紐づけていきます。流れとしては以下の通り

  • 山田太郎(管理者)山田花子(編集者)というテストユーザーを作成する
  • admineditorというロールを作成する
  • edit articlesdelete articlesという権限を作成する
  • adminロールに対して、edit articlesdelete articles権限を紐づける
  • editorロールに対して、edit articles権限を紐づける
  • 山田太郎(管理者)ユーザーにadminロールを割り当て、山田花子(編集者)ユーザーにeditorロールを割り当てる

シーダーファイルとしては以下のようになります。

Database\Seeders\RolesAndPermissionsSeeder.php
<?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にミドルウェアとして登録します

App/Http/Kernel.php
protected $routeMiddleware = [
    'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
    'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
    'roleOrPermission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];

これにより、ミドルウェアとして使用できるようになるので、ユースケースに合わせて下記のように実装していきます

api.php
// 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 () {
    // ・・・
});

②コントローラー内で認可処理を実施する

コントローラーで処理をするパターンです。個人的な感覚ではこちらのパターンで実装することが多いです

App\Http\Controllers\TestController
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を利用したロールベースアクセス制御の実装が完了です。今回初めて使用したので、何か気付いたところがあればコメントで教えていただけると嬉しい限りです

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0