coucounco / laravel-acl
Laravel 访问控制列表
Requires
- php: >=8.1.0
- illuminate/auth: ^10.0
- illuminate/container: ^10.0
- illuminate/contracts: ^10.0
- illuminate/database: ^10.0
Requires (Dev)
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^9
This package is auto-updated.
Last update: 2024-09-09 09:38:03 UTC
README
这是一个为 Laravel 6.0|7.0|8.0|9.0 提供访问控制列表的包。
对于 Laravel 6.0|7.0|8.0 使用 v1 版本。
对于 Laravel 9.0 使用 v2 版本。
入门指南
此包可以通过 Composer 安装
composer require coucounco/laravel-acl
安装后,您必须执行以下步骤
1) 在 config/app.php 文件中添加服务提供者
'providers' => [
// ...
coucounco\LaravelAcl\ServiceProvider::class,
];
2) 在您的应用程序中发布 laravel-acl 配置
此步骤将复制配置文件到您的 Laravel 应用配置文件夹中。
config/acl.phpconfig/acl/users.php
php artisan vendor:publish --provider="coucounco\LaravelAcl\ServiceProvider"
发布后,您可以通过 config/acl.php 文件管理 laravel-acl 的配置,它包含
<?php
return [
/*
* Defaults for laravel-acl
*/
'defaults' => [
/**
* The acls consists in a set of permissions for a given entity.
* Here you can set the default acls (acls defined in the models section of this config file) used by laravel-acl
*/
'acls' => 'users',
],
/**
* Here you map models to acls.
*
* You can add new row by adding :
* [Model] => [acls_name]
*
* After adding a new line here, you will need to add a new configuration files under config/acl/[acls_name].php
*/
'models' => [
App\Models\User::class => 'users',
],
/**
* Cache configuration
*/
'cache' => [
'enable' => true,
'key' => 'laravel-acl_',
'store' => '',
'expiration_time' => 432000
],
];
3) 配置 acls
laravel-acl 不仅提供 acls 和权限给一个模型(默认 App\Models\User),还可以配置多个。默认情况下,使用 users 模型,使用模型 App\Models\User。但您可以根据需要添加更多 acls。
'defaults' => [
'acls' => 'users',
],
'models' => [
App\Models\User::class => 'users',
],
示例
'defaults' => [
'acls' => 'users',
],
'models' => [
App\Models\User::class => 'users',
App\Models\Member::class => 'members',
],
每个 acls 都有一个相关的配置文件。 users 有 config/acl/users.php 并包含以下内容
<?php
return [
/**
* Register every permissions here
* key is the name of the permission
* value is the id of the permission
* Every permissions can have a different access level
* 0 = ACL_NONE -> no permission
* 1 = ACL_READ -> read permission
* 2 = ACL_CREATE -> create permission
* 3 = ACL_UPDATE -> update permission
* 4 = ACL_DELETE -> delete permission
* Access level are incrmental. If user has a permission with an access level of ACL_CREATE
* it means that the user can ACL_READ and ACL_CREATE
*/
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
],
/**
*
*/
'roles' => [
'admins' => "1",
'user' => "0",
],
'model' => [
// direct acl on user
'user' => [
/**
* Enable acl for user
*/
'enableAcl' => true,
/**
* The attribute where the acl is stored in the User model.
* It's basically the name of the column in the database
*/
'attributeName' => 'acl',
],
// acl via groups of user
// n-n relation between user and group
'group' => [
/**
* Enable acl for group
*/
'enableAcl' => false,
/**
* The name of the relationship from the User model to the "group" model
*/
'relationship' => 'groups',
/**
* The attribute where the acl is stored in the "group" model.
* It's basically the name of the column in the database
*/
'attributeName' => 'acl',
]
],
'cache' => [
'key' => 'laravel-acl_',
'store' => '',
'expiration_time' => 432000
]
];
3) 配置用户 ACL
可选地,您可以在 User 上启用直接 acl
要启用此功能,您必须编辑 config/acl/users.php 文件中的 model.user.enableAcl 并执行以下说明。
如果您不想在用户上启用直接 acl,请跳到下一章。
3.1) 更新 User 模型
在您的 User 模型中添加 UserAcl 特性。
namespace App;
...
use coucounco\LaravelAcl\Traits\UserAcl;
class User extends Model {
use UserAcl;
...
}
3.2) 在 users 表中添加 acl 列
创建一个新的迁移文件以更新 users 表
php artisan make:migration add_acl_in_users_table --table=users
并添加新列
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAclInUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->text('acl')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('acl');
});
}
}
默认情况下,此列的名称为
acl,但您可以通过在config/acl/users.php文件和此迁移文件中更新model.user.attributeName来更改它。
4) 配置组 ACL
可选地,您可以启用组 acl。
要启用此功能,您必须编辑 config/acl/users.php 文件中的 model.user.enableAcl 并执行以下说明。
如果您不想在用户上启用直接 acl,请跳到下一章。
4.1) 设置数据库表
要启用组 acl,您必须创建更多表或更新现有的表。
您需要一个 groups 表和中间表 group_user 以创建多对多关系。(如果您有不同的命名方式也行)
如果您需要创建这些表,请按照第 4.1.1 节进行操作,否则按照 4.1.2 节进行操作。
4.1.1) 创建表
如果您已经有一个与
User的多对多关系相似的分组表,则不要创建这些表。
创建一个新的迁移文件以创建 groups 表
php artisan make:migration create_groups_table
内容如下
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('groups', function (Blueprint $table) {
$table->bigIncrements('id');
$this->string('name');
$this->text('acl')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('groups');
}
}
可以更改
acl列的名称,方法是在config/acl/users.php文件和此迁移文件中更新model.group.attributeName。
添加一个新的迁移文件以创建名为 group_user 的中间表
php artisan make:migration create_group_user_table
内容如下
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGroupUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('group_user', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('group_id');
$table->foreign('user_id')
->references('id')->on('users');
$table->foreign('group_id')
->references('id')->on('groups');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('group_user');
}
}
这就是创建数据库表的全部内容。
4.1.2) 更新表
在您的分组表中添加 acl 列。
创建一个新的迁移文件以更新您的分组表。
确保您有正确的表名。
php artisan make:migration add_acl_in_groups_table --table=groups
并添加新列
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAclInUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('groups', function (Blueprint $table) {
$table->text('acl')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('groups', function (Blueprint $table) {
$table->dropColumn('acl');
});
}
}
默认情况下,此列的名称为
acl,但您可以通过在config/acl/users.php文件和此迁移文件中更新model.group.attributeName来更改它。
数据库表更新完成。
4.2) 更新群组模型
在你的Group模型中添加GroupAcl特质。你还需要将关系添加到User模型。
namespace App\Models;
...
use coucounco\LaravelAcl\Traits\GroupAcl;
class Group extends Model
{
use GroupAcl;
...
public function users() {
return $this->belongsToMany('App\User');
}
}
4.3) 更新User模型
将关系添加到User模型。
如果你的群组表有不同的名称,这没有问题。你只需更新model.group.relationship,并在config/acl/users.php文件中的关系函数上设置此名称。
namespace App;
class User extends Model {
...
public function groups() {
return $this->belongsToMany('App\Group');
}
}
5) 享受吧!
一切准备就绪,现在跳转到文档部分,了解更多关于laravel-acl的信息。
文档
本章解释了laravel-acl是如何工作的,并描述了可用的工具(助手、中间件等)。
定义权限和角色
权限和角色以硬编码的方式在config/acl/users.php文件中管理。这个选择是为了简化使用并尽可能避免数据库查询。
权限
您可以通过在config/acl/users.php文件中的permissions数组中添加新条目轻松添加权限。
键是权限的名称,值是标识符
必须有一个superadmin权限,其标识符设置为0。
您可以按照自己的方式管理其他所有权限。
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
'run_page_import' => 9,
],
角色
角色是一组预置权限。您可以使用config/acl/users.php文件中的roles数组来管理角色。
键是角色的名称,值是ACL。
'roles' => [
'admins' => "1",
'user' => "4110",
],
ACL
什么是ACL?
这是一个字符串值,用于定义用户或组的权限。
默认情况下,此值存储在users表的acl列和群组表中。
让我们以下面的ACL为例。
"1000003410"
如果我们定义了以下权限。
'permissions' => [
'superadmin' => 0,
'user' => 1,
'group' => 2,
'page' => 3,
'run_page_export' => 8,
'run_page_import' => 9,
],
ACL是从右到左读取的。
每个数字代表什么?
- ACL“1000003410”中的第一个数字“0”代表标识符为“0”的权限。在我们的例子中是
superadmin权限。 - 第二个数字“1”代表标识符为“1”的权限(这是
user权限)。 - 第四个数字“3”代表
page权限。 - 第八个数字“0”代表
run_page_export权限。 - 最后一个数字(第九个)是“1”,代表
run_page_import权限。
但是,这些值“0”、“1”、“2”、“3”、“4”在每个数字上代表什么?
这些值定义了给定权限的访问级别。
所以,描述ACL“1000003410”,用户有以下权限/限制
- 用户不是
superadmin; - 用户对
user权限有读访问权限; - 用户对
group权限有删除访问权限; - 用户对
page权限有更新访问权限; - 用户不能执行
run_page_export; - 并且用户允许执行
run_page_import。
您已经了解了关于权限、角色和ACL的所有内容。跳到下一章学习如何授予和撤销权限
授予和撤销权限
给用户
如何给用户授予superadmin权限
$user->grantPermission('superadmin', ACL_ALLOW);
$user->save();
如果不保存,权限将不会持久化到数据库中。
如何给用户授予对group权限的读访问权限
$user->grantPermission('group', ACL_READ);
$user->save();
如何给用户授予对page权限的删除访问权限
$user->grantPermission('page', ACL_DELETE);
$user->save();
如何一次性授予多个权限
$user->grantPermissions([
'page' => ACL_READ,
'user' => ACL_UPDATE
]);
$user->save();
如何撤销权限
$user->revokePermission('user');
$user->save();
或者您也可以授予ACL_NONE或ACL_DENY级别。
$user->grantPermission('user', ACL_DENY);
$user->save();
如何撤销多个权限
$user->revokePermissions(['user', 'group']);
$user->save();
如何撤销所有权限
$user->revokePermissions();
$user->save();
给群组
它与用户的方式相同。
$group->grantPermission('user', ACL_READ);
$group->save();
$group->grantPermissions([
'user' => ACL_READ,
'page' => ACL_UPDATE,
'run_page_export' => ACL_ALLOW
]);
$group->save();
$group->revokePermission('user');
$group->save();
$group->revokePermissions(['user', 'run_page_export']);
$group->save();
现在您已经学会了如何授予和撤销用户或组的权限,接下来您需要学习如何检查用户的权限。
检查访问权限
本章描述了检查用户是否有权限访问页面或执行操作的每一种方法。
权限门
您可以使用由laravel提供的Gate门面。
Gate::allows('user', [ACL_CREATE]);
用户模型
您可以使用Laravel中的can方法来检查User权限。
检查用户是否能读取页面
$hasPermission = auth()->user()->can('page', [ACL_READ]);
如果用户能够读取页面,则返回true,否则返回false。
检查用户是否在给定组的作用域内可以编辑用户
$group = Group::find(1);
$hasPermission = auth()->user()->can('page', [ACL_READ, $group]);
只有当用户获得给定组的访问权限时才返回true,否则返回false。
这对于管理与特定组相关联的实体的访问非常有用。
检查用户是否在多个组的作用域内可以更新页面
$group1 = Group::find(1);
$group2 = Group::find(12);
$hasPermission = auth()->user()->can('page', [ACL_READ, collect([$group1, $group2])]);
第二个参数(组)必须是
Illuminate\Support\Collection集合。
中间件
您可以使用laravel-acl提供的acl中间件来直接在路由文件(routes/web.php)中保护路由或整个资源。
限制具有给定权限和级别的用户的访问
Route::get('users/index', 'UserController@index')->name('users.index')->middleware('acl:user:1');
此路由将只允许具有
user权限且具有ACL_READ级别的用户访问。
限制具有给定权限和级别的用户的访问
Route::get('users/index', 'UserController@index')->name('users.index')->middleware('acl:user:1|group:1');
此路由将只允许具有
user权限且具有ACL_READ级别或具有group权限且具有ACL_READ级别的用户访问。
Blade
在blade视图中隐藏一些按钮很有用。为了实现这一点,您可以使用Laravel提供的一些指令。
@can blade指令
@can('user', [ACL_READ])
allow
@else
denied
@endcan
等同于编写
@if(auth()->user()->can('user', [ACL_READ]))
allow
@else
denied
@endif
@cannot blade指令
@cannot('user', [ACL_READ])
denied
@else
allow
@endcannot
@canany blade指令
@canany(['user', 'page'], [ACL_READ])
The user has page or user permisson with a read level
@elsecanany(['group'], ACL_READ)
Or the user has the group permission with a read level
@else
denied
@endcannot
辅助函数
检查权限
检查用户是否能读取页面
acl_has_permission($user, 'page', ACL_READ)
检索权限和角色
您可以使用辅助方法检索所有权限。
$permissions = acl_permissions()
获取其他acls的权限,只需传递acls的名称作为参数
acl_permissions('members')
您可以使用辅助方法检索所有角色。
$roles = acl_roles()
获取其他acls的角色,只需传递acls的名称作为参数
acl_permissions('members')
strict选项
有时,您可能希望检查用户是否严格拥有权限。
这是什么意思?
示例
$user1拥有superadmin权限$user2拥有is_manager权限
因此,当您检查$user1是否具有is_manager权限时
$user1->can('is_manager');
即使他没有
is_manager权限,因为他是superadmin,这也会返回true。
可以使用具有严格参数的权限进行检查。
$user1->can('is_manager', ACL_STRCT);
即使用户是
superadmin,这也会返回false。
$user2->can('is_manager', ACL_STRCT);
这会返回
true,因为$user2拥有is_manager权限。