PHP-Casbin:一个让开发者不再为权限控制 “重复造轮子” 的工具

php-casbin 权限
今天想和大家聊聊这个陪伴我从 “个人侧写” 到 “企业级解决方案” 的开源项目,一个让 PHP 开发者不用再为权限控制 “重复造轮子” 的工具。

从 2018 年发布第一个版本,到现在 GitHub 1.3k + Star,PHP-Casbin的成长,其实是无数 PHP 开发者 “权限痛点” 的解决方案集合。

如果你也曾在项目里写过if($role == 'admin')的硬编码,或是为多租户权限隔离挠破头,那这篇文章,或许能给你一个更优雅的答案。

那些踩过的致命权限坑

曾经接手过一个电商 SaaS 项目的权限重构。当时的代码让我至今印象深刻:100 多个控制器里,每个方法都嵌着权限判断逻辑,比如订单列表页要写“管理员看所有、商家看自己的、客服看分配的”,光是这一段逻辑,在不同模块里重复了 20 多次。

更致命的是,业务迭代中暴露的许多问题:

1. 硬编码逻辑:改一个权限,牵出 10 个 bug

当时项目里的权限判断全是if-else嵌套,比如:

// 订单列表权限判断(项目代码片段)
if ($user->role == 'admin') {
    // 管理员查所有
    $orders = Order::all();
} elseif (\$user->role == 'merchant') {
    // 商家查自己的
    $orders = Order::where('merchant_id', $user->merchant_id)->get();
} elseif ($user->role == 'customer_service') {
    // 客服查分配的
    $orders = Order::where('cs_id', $user->id)->get();
}

当业务新增 “运营角色能看所有商家的未付款订单” 时,不得不在多个相关方法里加判断,如果漏改了几个,上线后直接导致运营看不到数据,这种 “牵一发动全身” 的痛,相信很多开发者都懂。

2. 权限模型单一:多场景需求无法满足

电商项目里,除了 “谁能看订单” 的RBAC需求,还有 “用户只能改自己的资料”(ACL)、“VIP 用户能访问会员接口”(属性权限)、“API 接口按 HTTP 方法控制”(RESTful)。

但当时的架构只能支持RBAC,为了实现其他需求,只能写额外的 “补丁代码”,最后权限逻辑乱成一团。

3. 无动态权限:临时授权要改代码

如果业务方紧急需求:“让某商家临时查看另一个商家的订单,只看 3 天”。

但现有架构里,要么给商家加 “管理员角色”(风险大),要么改代码加特殊判断(周期长),最后只能用临时表曲线解决, 这种“动态权限”的缺失,让系统灵活性大打折扣。

4. 多框架难兼容:换项目要重写权限

当时同时维护Laravelgin+gorm两个框架的项目,权限逻辑只能分开写两套。也没有一个公共维护权限的中间层,不用框架、不同语言的项目各自维护各自的项目权限。

正是这些痛点,才想寻求找一个:轻量、灵活、跨框架跨语言的权限框架,让开发者不用再为权限逻辑消耗精力

那就是Casbin,其核心思想是策略与模型分离,并且支持多种编程语言及主流框架的快速集成,为开发者提供了覆盖ACLRBACABAC等数十种模型的灵活权限控制方案,企业可在混合技术栈中维护统一的权限体系,降低多系统协同成本。

PHP-Casbin 核心能力

经过 6 年迭代,PHP-Casbin 已经从 “简单的 RBAC 工具”,成长为覆盖 99% 权限场景的企业级框架。它的核心价值,都围绕 “让权限控制更简单” 展开:

1. 支持多种主流权限模型,一套框架搞定所有场景

不用再为不同业务写不同权限逻辑!PHP-Casbin 内置多种模型,你只需改配置文件就能切换:

模型类型 适用场景 示例需求
ACL 简单的用户 - 资源授权 “用户 A 能编辑文章 1”
RBAC 多角色权限管理 “管理员能看所有订单,商家只能看自己的”
RBAC with Domains 多租户 / 多域名隔离 “租户 A 的管理员不能操作租户 B 的数据”
ABAC 基于属性的动态权限 “用户只能查看自己创建的、未过期的订单”
RESTful API 接口权限控制 “GET /api/orders 允许,POST /api/orders 仅管理员允许”

比如要实现 “多租户 RBAC”,只需在模型文件(model.conf)里加一行配置:

[request_definition]
r = sub, dom, obj, act

[policy_definition]
p = sub, dom, obj, act

[role_definition]
g = _, _, _ # 第三个参数表示domain(租户)

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act

然后在策略里定义 “租户 A 的 admin 角色能访问租户 A 的订单”:

p, admin, tenantA, /order, read  # 角色admin在tenantA下能读/order
g, alice, admin, tenantA         # 用户alice是tenantA的admin

这样一来,alice 只能访问 tenantA 的订单,完全隔离其他租户数据,不用写一行业务代码,全靠配置策略实现。

2. 轻量无侵入,3 步集成到任意项目

很多开发者担心 “引入权限框架会增加项目复杂度”,但 Casbin 从设计之初就坚持 “最小侵入”:

PHP-Casbin为例,其核心包仅 300KB,无冗余依赖,通过Composer安装时,除了核心代码,不会引入过多其他库,避免给项目 “增重”:

composer require casbin/casbin

PHP-Casbin支持几乎所有主流PHP框架的快速集成,不管你用LaravelThinkPHPYii2WebmanHyperfEasySwoole等,还是原生 PHP,都能无缝集成。以Laravel为例,只需 3 步:

# 1. 安装适配包
composer require casbin/laravel-authz

# 2. 发布配置文件,执行sql迁移
php artisan vendor:publish
php artisan migrate

# 3. 执行权限决策
// to check if a user has permission
if (Enforcer::enforce("eve", "articles", "edit")) {
    // permit eve to edit articles
} else {
    // deny the request, show an error
}

不同框架模型和策略配置逻辑完全一致,换框架不用重新学权限逻辑。它的策略支持多种存储方式:策略规则想存在哪就存在哪。权限策略(谁能访问什么资源)可以存在文件、MySQL、Redis、MongoDB 等地方,切换时只需改配置。

3. 动态权限管理:不用改代码,实时调整权限

业务方经常需要 “临时给某个用户开权限”,PHP-Casbin 提供了完整的 API 来动态操作权限:

// 给用户bob添加“读/order”权限
$enforcer->addPolicy('bob', '/order', 'read');

// 给用户bob添加admin角色
$enforcer->addRoleForUser('bob', 'admin');

// 禁止用户bob访问/order
$enforcer->addPolicy('bob', '/order', 'read', 'deny');  // 支持allow/deny

// 批量删除权限
$enforcer->removePolicies([['bob', '/order', 'read']]);

这些 API 可以集成到你的 “权限管理后台”,让运营或管理员自己调整权限,不用开发介入。

4. 性能优化:支持缓存和批量检查

当项目用户量达 10 万 + 时,权限检查的性能很关键 PHP-Casbin 做了两点优化:

  • 规则缓存:把常用的权限规则缓存到 Redis,避免每次检查都查数据库;
  • 批量检查:一次检查多个权限,减少 IO 次数:

场景案例

PHP-Casbin 可以用于电商、SaaS、政企等领域的企业级应用,这里分享几个典型案例,看看它在实际项目中如何发挥价值:

案例 1:电商平台 —— 多角色权限隔离

某知名电商平台(日活 50 万 +)用 php-casbin 实现了 “平台管理员 - 商家 - 客服 - 买家” 的四层权限体系:

  • 平台管理员:能查看所有商家数据、配置全局规则;

  • 商家:只能操作自己店铺的商品、订单,看不到其他商家数据;

  • 客服:只能处理分配给自己的售后工单,不能修改商品价格;

  • 买家:只能查看自己的订单、修改个人信息。

案例中的核心问题是 “商家数据隔离”,通过 “RBAC with Domains” 模型,把每个商家作为一个 “domain”,权限规则绑定到 domain 上,彻底解决了 “商家越权查看数据” 的问题。

案例 2:SaaS 服务 ——API 接口权限控制

某 SaaS 服务商(服务 1000 + 企业客户)用 php-casbin 管理旗下 200 + 个 API 接口的权限:

  • 给不同套餐的客户分配不同接口权限(基础版能调用用户接口,企业版能调用数据分析接口);

  • 结合 JWT 令牌,在网关层自动校验每个 API 请求的权限;

  • 客户升级套餐时,通过 API 自动开放更多接口权限,不用人工操作。

如果用 “接口白名单” 的方式管理权限,每次新增接口都要改配置。用 php-casbin 后,接口权限通过策略规则管理,新增接口只需加一条规则,而且支持 “按接口前缀控制”(比如/api/v1/*)。

案例 3:政企系统 —— 动态权限与审计

某政务系统(涉及敏感数据)用 php-casbin 实现了 “基于角色 + 属性” 的权限控制:

  • 基础权限用 RBAC(比如 “科室管理员能看本科室数据”);

  • 动态权限用 ABAC(比如 “只有工作日 9:00 -18:00 能修改数据”);

  • 所有权限操作都记录审计日志,满足等保要求。

传统的权限系统无法支持 “时间限制”,只能通过定时任务开关权限。用 php-casbin 的 ABAC 模型后,只需在匹配器里加时间判断:

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act && r.now >= "09:00" && r.now <= "18:00"

然后在检查权限时传入当前时间:

$enforcer->enforce('user1', '/data', 'edit', ['now' => date('H:i')]);

这样就实现了 “仅工作时间能修改数据”,不用写任何定时任务。

写在最后

当微服务架构与云原生成为技术新常态,传统权限模型可能面临模型僵化、扩展困难、多语言协同繁琐等问题。

PHP-Casbin作为Casbin生态的 PHP 实现,通过统一的模型设计,为开发者提供了覆盖 ACL、RBAC、ABAC 等数十种模型的灵活权限控制方案,使用 Casbin 来做权限控制是一种跨平台、动态策略的现代化解决方案。

本作品采用《CC 协议》,转载必须注明作者和本文链接
专注于分享 Go、Java、Python、PHP、Node.js 等全栈技术开发领域知识,欢迎关注我的 技术圈
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3
Mutoulee

非常棒!

4个月前 评论

订单列表页要写 “管理员看所有、商家看自己的、客服看分配的”在,怎么实现?这是数据权限相关的,感觉是ai生成的文章

4个月前 评论
JonLee (楼主) 4个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
26
粉丝
10
喜欢
82
收藏
67
排名:355
访问:2.7 万
私信
所有博文
社区赞助商