两个非常棒的 Laravel 权限管理包推荐
角色和权限是许多 Web 应用程序的重要组成部分。 有很多为这个部分而写的包,随着 Laravel 历史的发展官方也提供了相关的支持。那么今天这块市场的情况如何?有什么包是最好用的么?这里我有两个推荐。
为什么需要包?
追本遡源 —— Laravel 官方权限功能支持在 5.1.11 版中引入之后就几乎没变过。大概有这些东西:
- Gates 和 Policies
- $this->authorize() 方法
- @can 和 @cannot Blade 命令
有人可能会说直接用 Laravel 自带的用户授权就足够了,没有必要再用别的软件包了。这是旧包被遗弃的原因之一:自带的功能取代了它们。
但是,在这个领域仍然有这样一些包可以帮助我们实现 Laravel 核心功能不容易实现的权限和角色需求。有两个包做得很好,作者也还在积极维护:
特别提及:santigarcor/laratrust,它是已经停止维护的 Entrust 的一个 fork 分支,不然可能会成为强大的第三位选手。 Laratrust 的问题是使用自己的 Laravel 命令替换默认 Laravel 命令,因此无法使用 Gates 或 @can 语法。相反,你需要使用 $user->can(‘edit-user’) 或 @permission Blade 命令。但是如果你不关心这些额外的语法,Laratrust 会是一个很棒的包。它还具有 Spatie 和 Bouncer 的包中没有的团队功能。
还有其它的几个选择,大部分似乎都过时了然后也很久没有被维护了。不过,你可能还是有希望看到他们卷土重来的:
现在,让我们深入了解一下今天两个主角吧。
这些包实际上是做什么的?
他们提供了一个更容易处理角色和权限的 API。此外,最终的代码更容易阅读也更容易理解。
你可以简单使用以下代码来代替分散在不同地方的 Policies 和 Gates 里创建的权限规则:
$user->givePermissionTo('edit articles'); // Spatie 的包
$user->allow('ban-users'); // Bouncer 的包
基本上,这两个包提供了类似的功能,只是语法和数据库结构略有不同。 接下来进行一个深入的比较。
安装和使用
两个包的安装类似:
- 添加到 composer 安装;
- 在
config/app.php
中添加一个提供器和 facade (Bouncer); - 发布和运行迁移;
- 在用户模型中添加一个特殊的 trait ( 这两个包都使用了 Traits);
- 使用包的方法 ( 有需要的话还能选择性地包含它的类).
这两个包都已经假设你已经有一个默认的 Laravel 用户数据库表,但没有任何角色和权限的结构。 它们会添加自己的表和字段。
这两个包都在 README 上有非常清晰的文档来描述各自的用法。
数据库结构
这是这两个包完全不同的地方。 Spatie 的包有以下表:
这里有一些解释:
- 字段 guard_name 具有默认值 web — 允许你使用多个 guard;
- 正如你看到的,有两个权限的 中间表 — 角色和用户;
- 字段 model_type 具有默认值 App\User ,所以没有直接外键关联到 users 表,也没有其他表有 user_id 字段。
现在我们来看看 Bouncer 的数据库:
看起来很不一样?Bouncer 的设计的关联更少。让我来解释一下:
- 权限,Spatie 称之为 permissions, Bouncer 称之为 abilities。 然后,permissions 是附加到 entity 的一组功能;
- Entity (在所有表中)是分配能力的对象。它可能是角色或用户。因此,与 user_id 或者 users 表没有直接关联,这跟 Spatie 的包一样;
- 还有一些不同于前者的字段:abilities.title,abilities.only_owned 和 roles.level。他们添加了一些附加功能,但在 README 文件中并没有很好的解释;
- Spatie 有 guard 字段但是 Bouncer 没有。
总而言之,Bouncer 的数据库结构似乎更复杂一些,更难于理解,但随之而来的灵活性更大。
可用方法
这两个包确实提供了类似的功能,所以接下来比较一下细节。
创建角色/权限/能力
Spatie
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
Role::create(['name' => 'writer']);
Permission::create(['name' => 'edit articles']);
Bouncer
你可以用简短的一句来创建角色和能力:
Bouncer::allow('admin')->to('ban-users');
简单这样写,Bouncer 会在后台为你创建一个 Role 模型和一个 Ability 模型。
你也可以使用 Facade 这样写:
use Silber\Bouncer\Database\Ability;
Ability::create(['name' => 'edit articles']);
正如你所看到的,Bouncer 具有更多的功能,比如自动创建模型。
将角色分配给用户
Spatie
$user->assignRole('writer');
$user->assignRole(['writer', 'admin']);
$user->removeRole('writer');
角色也可以同步:
// 所有当前角色将从用户中删除并替换为给定的数组
$user->syncRoles(['writer', 'admin']);
Bouncer
$user->assign('admin');
$user->assign(['writer', 'admin']);
$user->retract('admin');
非常好的一点是两个包都可以接受单独的角色或数组。
由于 Spatie 的包拥有角色同步 syncRoles 这个功能,在这一部分略胜一筹。这真的是一个很有用的功能,因为如果用 Bouncer 你需要手动执行几个操作。
为用户分配权限/能力
Spatie
$user->givePermissionTo('edit articles');
$user->givePermissionTo('edit articles', 'delete articles');
$user->revokePermissionTo('edit articles');
Bouncer
$user->allow('ban-users');
$user->allow(['ban-users', 'edit-articles']);
你可以将模型名称作为第二个参数传递。
Bouncer::allow($user)->to('edit', Post::class);
Bouncer::allow($user)->to('edit', $post);
$user->disallow('ban-users');
Bouncer::disallow($user)->to('delete', Post::class);
虽然都是类似的功能,但 Bouncer 提供了传递模型类或模型实例的能力。
检查用户的权限/角色
Spatie
检查角色
$user->hasRole('writer');
$user->hasAnyRole(Role::all());
$user->hasAllRoles(Role::all());
检查权限
$user->can('edit articles');
$role->hasPermissionTo('edit articles');
Bouncer
检查角色
$user->isAn('admin');
$user->isA('subscriber', 'editor');
$user->isAll('editor', 'moderator');
$user->isNot('subscriber', 'moderator');
检查权限
Bouncer::allows('edit articles')
这个部分在两个包中都非常相似,不分高下。
Blade 命令
Spatie
@hasanyrole('writer|admin')
I have one or more of these roles!
@else
I have none of these roles...
@endhasanyrole
Bouncer
Bouncer 没有添加自己的 Blade 指令。
Spatie 包则增加了几个指令。 当然,这两个包都可以使用默认的 Laravel 命令,如 @can 和 @endcan。
高速缓存
Spatie
角色和权限数据被自动缓存以加快性能。
要手动重置这个包的缓存,请运行:
php artisan cache:forget spatie.permission.cache
Bouncer
bouncer 当前请求执行所有查询都会缓存。如果启用了跨请求缓存,缓存会在不同请求之间共享。
无论何时,只要你需要,都可以刷新 bouncer 的缓存:
Bouncer::refresh();
或者,你可以只为特定用户刷新缓存:
Bouncer::refreshFor($user);
在 Bouncer 中缓存有一些更强大的功能。比如启用/禁用缓存,为特定用户刷新缓存也可能会方便。
最终结论
在这里没办法告诉你这两个包哪个更好,因为这两个包都真的很好,这已经上升到了一个偏好的问题。
他们都有自己的一些功能的优势,甚至更多的细节上的设计。
Spatie 的优点:
- 文档更好 ( Bouncer’s 的一些方法没有在 README 中被提到)
- 更容易理解的数据库结构
- syncRoles() 方法可以代替删除插入
- 一些 blade 命令 —— @role 和 @hasanyrole
- 支持多个 guard
Bouncer’s 的优点:
- 更优雅的创建角色和权限
- 基于模型或实例的权限控制
- 更好的缓存机制
- 更强大的数据库结构和一些更有用的字段
如果以上任何一个细节对你来说非常重要,那可能会成就你选择的决定。否则,选择 Spatie 或 Bouncer,都不会让你失望。
附一个额外的礼物
最后,这两个包都提供了一组功能来管理角色和权限,但没有任何 UI 或管理面板进行管理。我准备了一个基于这两个包的 UI 入门工具包。你可以使用它作为样板来管理角色和权限。
以下是 GitHub 上的链接:
本作品采用《CC 协议》,转载必须注明作者和本文链接
搬运工。。不多说先点个赞..
有没有做过酒店管理的童鞋,不知道你们在角色和权限这块是怎么搞的。特别是携程网这种多个酒店的~有做过的出来讨论下嘿~
以前项目用的 Zizaco / entrust 包,居然停更了,都没注意。
方便问一下,有没有哪个包支持这三个功能的:
Laravel-permission 在我心中排第一。:+1:
不知道有没有基于lumen的权限包,我们做的前后端分离的spa也需要权限控制。
santigarcor/laratrust挺不错的
@翁航 第二个好解决吧?你在业务上限制只可以分配一个角色不就好了
粗粒度的权限,还是直接自带的
acl
搞定,细粒度的权限,直接是laratrust
你好,kodeine/laravel-acl我以api形式开发,搞不懂,请问你那边有相关这边的项目吗
Zizaco / entrust 停止更新了嘛? 我github上的时间在7个月之前有更新。
谢谢 分享 最近一直在学习做这个
不知道是否支持多用户呢?比如一个会员(多级会员不同权限),一个管理员(总管理及分销商)这样
需求没法用这类通常的权限管理,因为需要权限自治,还是无限级自治模式
展示表关联关系是用的什么软件啊
@atao mysql workbench
令人不解,为什么 Laravel-permission 要增加 guard 的区分,这从逻辑上有意义吗?
web 和 api 这两个 guard 必然是共用 RBAC 权限信息的呀
我觉得,这些权限包,都不会特别长久,挥着长期提供思路。因为不同类型产品的用户权限控制都是不同的。尤其是又一个神pm的时候,得跪。
看到小学姐这么强,我深感惭愧
问一个问题。。。使用laravel-permission有如下场景:
怎么才能取消user的p1权限?(求解答)
学习了 tks
这个laravel-permission原来最新版本是不支持php5.6的 无语.........
请问:如果有多个guard的话,在中间件中,该如何设置?github的usage中,没有对这块进行说明
Bouncer 好用自由度很高,通用性很强适合更复杂的权限逻辑开发, 缺点文档只是简单的使用和运用介绍,理解还是需要上手研究。
支持的功能有:
控制层+数据层权限管理设计思路:
学习了,很有用:smile:
emm......先研究一下,不知道能否实现某个菜单下,表格字段的控制(比如一个表格有 a,b,c,d 四个表头,我想让 A 用户只能看 a,b 这两个);
没看明白数据权限要怎么结合。。
请问如何在模版中使用?
上手使用感觉
laravel-permission
id
作为PRI,导致部分CRUD工具无法识别主键guard
会默认从配置中获取web
,这就要求Model类是要有guard_name
这个属性的。或者可以每次调用givePermissionTo
之前,单独指定属性。bouncer
permissions
表,用来存储了权限和ablities表的映射关系,但是这张表里面的entity_type
既可以是roles、又可以是Model类,entity_id
代表在entity_type
指向的表中的主键ablities
才是权限表总结
从刚刚进行适配的感觉来看,bouncer 更适合自由度更高的programer
推荐
这是一款可以根据MySQL的表结构生成CRUD后台的工具,在配合使用
laravel-permission
的时候,遇到了很多问题,就如刚刚提到的主键问题。配合bouncer
运行完美,可以修改后作为权限系统的UI。使用这两个包就可以不用中间件来做权限管理了是吗?