在 PHP 项目里做权限控制时,很多人先想到的是角色或固定规则匹配;但当判断条件和资源属性强相关时,ABAC 往往更直接。下面就用 PHP-Casbin 的官方示例拆开说明:模型怎么写、对象属性怎么参与判断,以及返回结果为什么会是 true 或 false。
ABAC 在 PHP-Casbin 里解决什么问题
PHP-Casbin 是一个开源访问控制框架,支持多种权限模型。ABAC 即“基于属性的访问控制”,它的关键点不是只拿主体、资源、动作这几个字符串去比对,而是把主体、客体或动作本身携带的属性纳入判断。
换句话说,如果权限规则依赖“这个资源是谁创建的”“当前用户是不是资源拥有者”这类业务字段,ABAC 会比单纯的字符串匹配更贴近实际场景。
官方示例的模型配置怎么理解
官方示例给出的 ABAC 模型如下:

[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == r.obj.owner
这里最值得注意的是匹配器:
m = r.sub == r.obj.owner
它表达的含义非常直接:当请求中的主体 r.sub 与资源对象 r.obj 的 owner 属性相等时,允许访问。也就是说,真正参与判断的是对象属性,而不只是对象名称。
从这个例子也能看出,ABAC 的重点是“把业务对象直接带进决策过程”。只要资源对象上有可供判断的属性,模型就可以围绕这些属性编写规则。
PHP 对象如何参与权限判断
示例里,r.obj 对应的是一个 PHP 对象,定义方式如下:
$data1 = new stdClass();
$data1->name = 'data1';
$data1->owner = 'alice';
$data2 = new stdClass();
$data2->name = 'data2';
$data2->owner = 'bob';
这里创建了两个资源对象,它们都有 name 和 owner 两个属性。对于当前这条规则来说,真正决定结果的是 owner:
$data1->owner = 'alice',表示data1的拥有者是alice。$data2->owner = 'bob',表示data2的拥有者是bob。
这也是 ABAC 和常见字符串规则的区别之一:资源不必先转换成一个固定标识再去比对,框架可以直接读取对象上的业务属性完成授权判断。
`enforce()` 返回结果为什么不同
将主体、对象和动作传给决策器后,示例中的判断结果如下:

$e->enforce('alice', $data1, 'read'); // true
$e->enforce('alice', $data2, 'read'); // false
$e->enforce('bob', $data1, 'read'); // false
$e->enforce('bob', $data2, 'read'); // true
按匹配器 m = r.sub == r.obj.owner 来看,结果并不复杂:
'alice'访问$data1时,$data1->owner正好也是'alice',因此返回true。'alice'访问$data2时,资源拥有者是'bob',因此返回false。'bob'访问$data1时,不满足拥有者一致,返回false。'bob'访问$data2时,拥有者一致,返回true。
可以把这个例子概括成一句话:谁是资源的拥有者,谁就能访问该资源。对于“用户只能操作自己创建的数据”这类需求,这种写法通常比单独维护大量显式规则更简洁。
如果你的权限判断依赖对象属性而不是固定角色名,PHP-Casbin 的 ABAC 就很值得优先考虑。先把资源对象的关键字段整理清楚,再把规则写进 matcher,通常就能得到足够直观的授权逻辑。













