两个非常棒的 Laravel 权限管理包推荐

file
角色和权限是许多 Web 应用程序的重要组成部分。 有很多为这个部分而写的包,随着 Laravel 历史的发展官方也提供了相关的支持。那么今天这块市场的情况如何?有什么包是最好用的么?这里我有两个推荐。

为什么需要包?

追本遡源 —— Laravel 官方权限功能支持在 5.1.11 版中引入之后就几乎没变过。大概有这些东西:

  • GatesPolicies
  • $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。此外,最终的代码更容易阅读也更容易理解。

你可以简单使用以下代码来代替分散在不同地方的 PoliciesGates 里创建的权限规则:

$user->givePermissionTo('edit articles'); // Spatie 的包
$user->allow('ban-users'); // Bouncer 的包

基本上,这两个包提供了类似的功能,只是语法和数据库结构略有不同。 接下来进行一个深入的比较。

安装和使用

两个包的安装类似:

  • 添加到 composer 安装;
  • config/app.php 中添加一个提供器和 facade (Bouncer);
  • 发布和运行迁移;
  • 在用户模型中添加一个特殊的 trait ( 这两个包都使用了 Traits);
  • 使用包的方法 ( 有需要的话还能选择性地包含它的类).

这两个包都已经假设你已经有一个默认的 Laravel 用户数据库表,但没有任何角色和权限的结构。 它们会添加自己的表和字段。

这两个包都在 README 上有非常清晰的文档来描述各自的用法。

数据库结构

这是这两个包完全不同的地方。 Spatie 的包有以下表:

file

这里有一些解释:

  • 字段 guard_name 具有默认值 web — 允许你使用多个 guard;
  • 正如你看到的,有两个权限的 中间表 — 角色和用户;
  • 字段 model_type 具有默认值 App\User ,所以没有直接外键关联到 users 表,也没有其他表有 user_id 字段。

现在我们来看看 Bouncer 的数据库:

file

看起来很不一样?Bouncer 的设计的关联更少。让我来解释一下:

  • 权限,Spatie 称之为 permissions, Bouncer 称之为 abilities。 然后,permissions 是附加到 entity 的一组功能;
  • Entity (在所有表中)是分配能力的对象。它可能是角色或用户。因此,与 user_id 或者 users 表没有直接关联,这跟 Spatie 的包一样;
  • 还有一些不同于前者的字段:abilities.titleabilities.only_ownedroles.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 上的链接:

参考链接:https://laravel-news.com/two-best-roles-pe...

本作品采用《CC 协议》,转载必须注明作者和本文链接
Stay Hungry, Stay Foolish.
本帖由 Summer 于 6年前 加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 30

搬运工。。不多说先点个赞..

6年前 评论

有没有做过酒店管理的童鞋,不知道你们在角色和权限这块是怎么搞的。特别是携程网这种多个酒店的~有做过的出来讨论下嘿~

6年前 评论
DukeAnn

以前项目用的 Zizaco / entrust 包,居然停更了,都没注意。

6年前 评论

方便问一下,有没有哪个包支持这三个功能的:

  • 支持多个guard (Spatie支持)
  • 一个用户只能属于一个角色,而不能有多个角色 (Spatie不支持)
  • 可以自定义用户模型,而不是强制使用User (Spatie支持)
6年前 评论
Destiny

Laravel-permission 在我心中排第一。:+1:

6年前 评论
森林

不知道有没有基于lumen的权限包,我们做的前后端分离的spa也需要权限控制。

6年前 评论

santigarcor/laratrust挺不错的

6年前 评论

@翁航 第二个好解决吧?你在业务上限制只可以分配一个角色不就好了

6年前 评论

粗粒度的权限,还是直接自带的 acl 搞定,细粒度的权限,直接是 laratrust

6年前 评论

你好,kodeine/laravel-acl我以api形式开发,搞不懂,请问你那边有相关这边的项目吗

6年前 评论

Zizaco / entrust 停止更新了嘛? 我github上的时间在7个月之前有更新。

6年前 评论

谢谢 分享 最近一直在学习做这个

6年前 评论

不知道是否支持多用户呢?比如一个会员(多级会员不同权限),一个管理员(总管理及分销商)这样

6年前 评论
GanymedeNil

需求没法用这类通常的权限管理,因为需要权限自治,还是无限级自治模式

6年前 评论

展示表关联关系是用的什么软件啊

6年前 评论

令人不解,为什么 Laravel-permission 要增加 guard 的区分,这从逻辑上有意义吗?

web 和 api 这两个 guard 必然是共用 RBAC 权限信息的呀

6年前 评论
medz

我觉得,这些权限包,都不会特别长久,挥着长期提供思路。因为不同类型产品的用户权限控制都是不同的。尤其是又一个神pm的时候,得跪。

6年前 评论

看到小学姐这么强,我深感惭愧

6年前 评论
问一个问题。。。使用laravel-permission有如下场景:
  • 用户组group有p1,p2,p3,p4权限。
  • 用户user属于group。

怎么才能取消user的p1权限?(求解答)

6年前 评论
user02 4年前
hezhizheng

这个laravel-permission原来最新版本是不支持php5.6的 无语.........

6年前 评论

请问:如果有多个guard的话,在中间件中,该如何设置?github的usage中,没有对这块进行说明

6年前 评论

Bouncer 好用自由度很高,通用性很强适合更复杂的权限逻辑开发, 缺点文档只是简单的使用和运用介绍,理解还是需要上手研究。

支持的功能有:

  • 1.多guard认证
  • 2.限定范围权限(比如不同平台下的角色和功能切换)
  • 3.可以直接关联功能节点
  • 4.数据权限管理
  • 5.可以高度自定义权限结构

控制层+数据层权限管理设计思路:

  • 1.因为bouncer扩展只提供model层的约束,所以要创建一个表来管理控制层的节点和数据层的节点。
  • 2.然后通过在能力表上添加基于这个管理model的记录范围约束增加对应的能力值即可。
  • 3.通过管理表上的记录类型就能区分权限的类型。
6年前 评论

学习了,很有用:smile:

5年前 评论

emm......先研究一下,不知道能否实现某个菜单下,表格字段的控制(比如一个表格有 a,b,c,d 四个表头,我想让 A 用户只能看 a,b 这两个);

5年前 评论

没看明白数据权限要怎么结合。。

5年前 评论

请问如何在模版中使用?

5年前 评论

上手使用感觉

laravel-permission

  1. 数据表设计,更加复杂一些
  2. 数据表进行设计的时候,并不是每张表都有id作为PRI,导致部分CRUD工具无法识别主键
  3. guard 会默认从配置中获取web,这就要求Model类是要有guard_name这个属性的。或者可以每次调用givePermissionTo之前,单独指定属性。

bouncer

  1. 数据表结构设计更简单,数据结构设计更加灵活,不仅仅是给用户设置权限,可以给任何Model设置(当然laravel-permission也可以)
  2. permissions表,用来存储了权限和ablities表的映射关系,但是这张表里面的entity_type既可以是roles、又可以是Model类,entity_id代表在entity_type指向的表中的主键
  3. ablities才是权限表

总结

从刚刚进行适配的感觉来看,bouncer 更适合自由度更高的programer

推荐

这是一款可以根据MySQL的表结构生成CRUD后台的工具,在配合使用laravel-permission的时候,遇到了很多问题,就如刚刚提到的主键问题。配合bouncer运行完美,可以修改后作为权限系统的UI。

https://github.com/sunshinev/laravel-gii
4年前 评论

使用这两个包就可以不用中间件来做权限管理了是吗?

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!