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 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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