back2lobby/access-control

laravel 的角色和权限管理器

v1.0.4 2023-06-03 11:39 UTC

README

Total Downloads License

AccessControl 是一个 Laravel 扩展包,用于简单易用的角色和权限管理,支持基于模型的角色分配和基于角色的权限。

目录

点击展开

简介

AccessControl 通过允许基于模型分配角色和定义基于角色的权限,简化了角色和权限管理,以便对用户访问进行细粒度控制。

安装完成后,您可以简单地告诉 access-control 在入口处允许什么

// Give a role some permission
AccessControl::allow("manager")->to('edit-company');

// Assign role to any user
AccessControl::assign('manager')->to($user);

// You can also assign role for a specific roleable model
AccessControl::assign('manager',$company)->to($user);

// Checking the permission on user for a roleable model
AccessControl::canUser($user)->do("edit-company",$company);

// Checking if the user has a role for that model
AccessControl::is($user)->a("manager",$company);

安装

注意:AccessControl 需要 PHP 8.1+ 和 Laravel 9.0+

  1. 使用 composer 安装 AccessControl

    composer require back2lobby/access-control
    
  2. 在用户模型中使用 HasRoles

    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Back2Lobby\AccessControl\Traits\HasRoles;
     
    class User extends Authenticatable
    {
     use HasFactory, HasRoles
    
     // code here
    }

    如果您想使用自定义用户模型而不是 App\Models\User,请参阅 自定义用户模型 部分。

  3. 如果您有一个可分配角色的模型,则将 AccessControl 的特质添加到您的可分配角色模型中

    use Back2Lobby\AccessControl\Traits\Roleable;
    class Post extends Model
    {
        use Roleable;
    }
  4. 现在,运行 AccessControl 的迁移。首先通过运行以下命令将迁移发布到您的应用 migrations 目录中

    php artisan vendor:publish --tag="access-control.migrations"
    
  5. 最后,运行迁移

    php artisan migrate
    

安装完成后,您可以使用生成器为您的 Laravel 应用程序创建基本角色和权限。例如

use Illuminate\Database\Seeder;
use Back2Lobby\AccessControl\Facades\AccessControlFacade as AccessControl;

class AccessControlSeeder extends Seeder
{
    public function run()
    {
        // Create all roles
        AccessControl::createManyRoles([
            [
                'name' => 'admin',
                'title' => 'Administrator',
            ],
            [
                'name' => 'editor',
                'title' => 'Editor',
            ]
        ]);

        // Create all permissions
        AccessControl::createManyPermissions([
            [
                'name' => 'create-post',
                'title' => 'Create Post',
                'description' => 'Allows user to create a new post',
            ],
            [
                'name' => 'edit-post',
                'title' => 'Edit Post',
                'description' => 'Allows user to edit an existing post',
            ],
        ]);
    }
}

外观

每次在代码中使用 AccessControl 外观时,请记住在文件顶部添加此行到命名空间导入

use AccessControl;

如果您的 IDE 在此外观方面有任何问题,请使用 barryvdh/laravel-ide-helper

术语

角色

可以分配给用户的权限集。

权限

执行特定操作或访问特定资源的权利。

直接权限

直接允许或禁止角色直接拥有的权限。

间接权限

用户因具有超级权限而拥有的权限,而不是直接允许或禁止。

超级权限

用于授予所有权限,除了直接禁止的权限。

直接角色

如果角色直接允许权限,则该角色是权限的直接角色。

间接角色

如果角色不直接允许权限,而是因为具有超级权限而拥有该权限,则该角色是权限的间接角色。

用法

角色

创建角色

可以使用 createRole 方法创建角色。示例

$superAdmin = AccessControl::createRole([
    'name' => 'super-admin',
    'title' => 'Super Admin'
]);

您还可以指定可分配的角色,这将限制为给定可分配的角色分配的角色。示例

AccessControl::createRole([
    'name' => 'manager',
    'title' => 'Manager',
    'roleables' => [Company::class]
]);

// ✓ assigning role with allowed roleable will work fine
$user->assign('manager',$company);

// ✗ assigning role with roleable that's not allowed will throw error
$user->assign('manager',$post);

可以一次创建多个角色,如下所示

AccessControl::createManyRole([
    ['name','company-manager','tittle'=>'Company Manager'],
    ['name','company-user','title' => 'Company User']
]);

更新角色

可以使用 updateRole 方法更新角色。示例

// using role name
AccessControl::updateRole('author',[
'name' => 'post-author',
'title' => 'Post Author'
]);

删除角色

可以使用 deleteRole 方法删除角色。示例

AccessControl::deleteRole('author');

获取角色

要检索一个角色,您可以使用方法 getRole。示例

AccessControl::getRole('admin');

要检索所有可用的角色,我们可以执行以下操作以获取可用角色的集合。

AccessControl::getAllRoles();

允许权限

要允许特定权限的角色,您可以使用方法 allow 并将其与方法 to 连接。示例

AccessControl::allow('author')->to('edit'); // with permission name

AccessControl::allow('author')->to($permission); // with permission object

AccessControl::allow('author')->to(3); // with permission id

或者,我们还可以直接从角色模型本身使用 allow 方法,如下所示

$role->allow('create-post');

要间接(除了特定禁止外)允许所有可用的权限,可以使用 superPermission 方法,如下所示

AccessControl::allow('super-admin')->superPermission();

方法 superPermission 需要名为 * 的权限。如果它不可用,它将创建它。

拒绝权限

使用方法 disallow 从用户中撤销权限,并将其与方法 to 连接。示例

AccessControl::disallow('admin')->to('create admin');

或者,我们还可以直接从角色模型本身使用 disallow,如下所示

$role->disallow('create-post');

要撤销分配给角色的超级权限,请使用方法 superPermission(),如下所示

AccessControl::disallow('manager')->superPermission();

禁止权限

使用方法 forbid 并将其与方法 to 连接来禁止角色的权限。示例

AccessControl::forbid('manager')->to('delete company');

或者,我们还可以直接从角色模型本身使用 forbid,如下所示

$role->forbid('create-post');

您可以使用方法 superPermission() 来间接禁止角色从所有权限中(除了特定允许外)。如下所示

AccessControl::forbid('manager')->superPermission();

获取角色的权限

要获取角色拥有的所有权限(包括允许和禁止),我们可以使用方法 getAllPermissionsOf,如下所示

$permissions = AccessControl::getAllPermissionsOf('manager');

要获取角色的特定类型权限,我们可以使用方法 getAllowedPermissionsOfgetDirectlyAllowedPermissionsOfgetIndirectlyAllowedPermissionsOfgetForbiddenPermissionsOfgetDirectlyForbiddenPermissionsOfgetIndirectlyForbiddenPermissionsOf。示例

 // getting allowed permissions
 $allowedPermissions = AccessControl::getAllowedPermissionsOf('manager');

 $directlyAllowedPermissions = AccessControl::getDirectlyAllowedPermissionsOf('manager');

 $indirectlyAllowedPermissions = AccessControl::getIndirectlyAllowedPermissionsOf('manager');

 // getting forbidden permissions
 $forbiddenPermissions = AccessControl::getForbiddenPermissionsOf('manager');

 $directlyForbiddenPermissions = AccessControl::getDirectlyForbiddenPermissionsOf('manager');

 $indirectlyForbiddenPermissions = AccessControl::getIndirectlyForbiddenPermissionsOf('manager');

如果您不了解直接/间接权限,请阅读 术语

分配角色

可以使用方法 assign 将角色分配给任何用户,并将其与 to 方法连接。或者,您可以直接在用户模型上使用可用的 assign 方法。示例

AccessControl::assign('admin')->to($user); // using facade

$user->assign('editor'); // using user model

如果角色需要特定的可分配角色,您也可以指定它,如下所示。例如,您想要一个用户仅作为一个特定项目的经理。这可以通过以下方式实现

AccessControl::assign('manager',$project)->to($user); // using facade

$user->assign('manager',$project); // using user model

撤销角色

可以使用方法 retract 从任何用户中撤销已分配的角色,并将其与 from 方法连接。示例

AccessControl::retract('admin')->from($user);

您还可以指定可分配的角色,仅撤销特定可分配角色的角色。例如,如果用户是多个公司的经理,则只会从用户中撤销给定公司的经理角色

AccessControl::retract('manager',$company)->from($user);

检查角色

要检查用户是否有特定角色,请使用方法 is 并将其与 aan 方法连接。示例

AccessControl::is($user)->a('manager',$company);

AccessControl::is($user)->an('admin');

要检查用户是否有特定角色,请将其与 notAnotAn 方法连接。示例

AccessControl::is($user)->notA('manager',$company);

AccessControl::is($user)->notAn('admin');

要检查用户是否有所有给定角色,我们可以这样做

AccessControl::is($user)->all([
    'admin',
    'manager'
]);

它不会检查任何角色可分配项,即使角色被限制在某些角色可分配项上。例如,如果用户拥有任何角色可分配项的经理角色,它将返回 true

AccessControl::is($user)->all([
    'manager'
]);

要检查用户是否有任何给定角色,我们可以这样做

AccessControl::is($user)->any([
    'admin',
    'manager'
]);

重置角色

要从一个角色中移除所有权限,我们可以使用方法 resetRole 来重置它。示例

AccessControl::resetRole('admin');

权限

创建权限

可以使用方法 createPermission 创建权限。示例

AccessControl::createPermission([
    'name' => 'edit-post',
    'title' => 'Edit Post'
]);

可以使用方法 createManyPermissions 一次创建多个权限,如下所示

AccessControl::createManyPermissions([
    ['name' => 'create-post','title' => 'Create Post'],
    ['name' => 'edit-post','title' => 'Edit Post'],
    ['name' => 'delete-post','title' => 'Delete Post']
]);

更新权限

可以使用方法 updatePermission 更新权限。例如,要将权限名称从 remove-post 更改为 delete-post,可以这样做:

AccessControl::updatePermission('remove-post',[
   'name' => 'delete-post',
   'title' => 'Delete Post'
]);

删除权限

要删除权限,可以使用方法 deletePermission,如下所示:

AccessControl::deletePermission('edit-post');

获取权限

要检索权限,可以使用方法 getPermission,如下所示:

AccessControl::getPermission('delete-company');

要检索所有可用权限,请使用方法 getPermissions。示例:

AccessControl::getPermissions();

获取具有权限的角色

要获取具有特定权限的所有角色,可以使用方法 getAllRolesOf,如下所示:

$rolesWhoCanEdit = AccessControl::getAllRolesOf('edit-post');

要获取特定类型的角色,我们可以使用方法 getAllowedRolesOfgetDirectlyAllowedRolesOfgetIndirectlyAllowedRolesOfgetForbiddenRolesOfgetDirectlyForbiddenRolesOfgetIndirectlyForbiddenRolesOf。示例:

// getting allowed roles
$allowedRoles = AccessControl::getAllowedRolesOf('edit-post');

$directlyAllowedRoles = AccessControl::getDirectlyAllowedRolesOf('edit-post');

$indirectlyAllowedRoles = AccessControl::getIndirectlyAllowedRolesOf('edit-post');

// getting forbidden roles
$forbiddenRoles = AccessControl::getForbiddenRolesOf('edit-post');

$directlyForbiddenRoles = AccessControl::getDirectlyForbiddenRolesOf('edit-post');

$indirectlyForbiddenRoles = AccessControl::getIndirectlyForbiddenRolesOf('edit-post');

如果您不了解直接/间接角色,请参阅术语

用户

获取用户角色

要获取用户分配的所有角色,可以使用由 Back2Lobby\AccessControl\Models\User 提供的方法 roles。示例:

$roles = $user->roles()->get();

获取用户权限

要获取通过各种角色允许用户的所有权限,可以使用由 Back2Lobby\AccessControl\Models\User 提供的方法 permissions。示例:

$roles = $user->permissions();

获取具有特定角色的用户

要获取具有特定角色的所有用户,可以使用由 Back2Lobby\AccessControl\Models\User 提供的静态方法 whereIs。示例:

$admins = User::whereIs('admin')->get();

如果目标角色限制了一些角色化对象,可以这样做:

$players = User::whereIs('player',$team)->get();

您也可以通过使用角色模型中的 users 方法来反转逻辑

$admins = $adminRole->users()->get();

获取具有特定权限的用户

要获取具有特定权限的所有用户,可以使用由 Back2Lobby\AccessControl\Models\User 提供的静态方法 whereHas。示例:

$users = User::whereHas('edit-post',$post)->get();

检查用户权限

要检查用户是否具有来自任何角色的特定权限,可以使用方法 canUser 并与方法 do 链接,如下所示:

$canCreatePost = AccessControl::canUser($user)->do('create-post');

您还可以这样指定角色化对象:

$canEditPost = AccessControl::canUser($user)->do('edit-post',$post);

重置用户

要从一个用户中移除所有角色,可以使用方法 resetUser。示例:

AccessControl::resetUser($user);

功能

缓存

所有角色和权限都进行了缓存,并且每天自动刷新一次。这种优化提高了性能并减少了不必要的数据库查询。请注意,用户数据没有缓存,因为它会频繁更改。

您可以使用 sync 方法手动与数据库同步所有角色和权限。例如:

AccessControl::sync();

要清除缓存,可以使用方法 clearCache,如下所示:

AccessControl::clearCache();

即使在清除缓存后,本地存储仍然会保留角色和权限,您也可以使用方法 reset 删除它们:示例

AccessControl::reset();

可以使用 cache 手动缓存存储:

AccessControl::cache();

注意:默认情况下,使用 file 作为缓存驱动程序,但可以在 access.php 配置文件中更改。

授权

在 blade 文件中检查角色和权限时,我们可以在用户模型上使用 Laravel 内置的 can 方法。例如:

if($user->can('view-dashboard')){
    // your code here
}

如果您想检查特定模型上的权限,则可以这样做:

$user->can('edit-company',$company);

Blade 指令

类似地,在 blade 文件中检查角色和权限时,我们可以使用 Laravel 内置的 @can 指令来检查。例如:

@can('ban-users')
	<button class="btn btn-danger">Ban User</button>
@endcan

@can('edit-post',$post)
	<a href="{{ route('post.edit') }}">Edit Post</a>
@endcan

配置文件

访问控制提供了一个配置文件,可以用于配置软件包的行为,包括指定缓存驱动程序和自定义用户模型。

您可以使用以下命令发布配置文件 access.php

php artisan vendor:publish --tag="access-control.config"

中间件

类似地,可以使用 Laravel 内置的 can 中间件:

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware('can:access-dashboard');

这将检查认证用户是否在处理请求之前具有访问-dashboard 权限。

您还可以使用 can 中间件来检查特定模型实例的权限。例如,以下路由将只针对具有在通过路由模型绑定传递给 /posts/{post}/edit 的 Post 模型实例上的 edit-post 权限的用户进行处理。

Route::get('/posts/{post}/edit', function () {
    return view('dashboard');
})->middleware('can:edit-post,' . Post::class);

在这种情况下,Post::class被传递以指定需要进行权限检查的模型类。请注意,这仅在路由为Post模型设置了路由模型绑定时才有效。

自定义用户模型

默认情况下,此包使用App\Models\User模型进行授权和认证。要使用自定义模型,需要以下步骤

  • access.php中指定模型。例如:
'auth_user_model' => CustomUserModel::class
  • 确保您的自定义用户模型继承自Illuminate\Foundation\Auth\User
  • 迁移与包相关的数据库表,或者使用以下命令获取一个新的数据库。
php artisan migrate:fresh
  • 注意:请确保您已在auth.php配置文件中指定了守卫的新认证模型。例如:
	'guards' => [
		'web' => [
			'driver' => 'session',
			'provider' => 'customUsers',
		],
	],

	'providers' => [
		'customUsers' => [
			'driver' => 'eloquent',
			'model' => App\Models\CustomUserModel::class,
		],
	],