PHP-Casbin 是一个非常流行的权限控制框架,支持ACL RBAC ABAC 等权限控制模型。

它使用 Matcher 中配置的表达式来做权限决策,不仅提供了非常多的内置函数,而且还可以在Matcher中指定自定义函数。

安装

如果你的项目还有没有引入Casbin依赖,则需要安装一下:

composer require casbin/casbin

决策器

这是演示的是纯原生PHP代码,先初始化一个决策器Enforcer。如果是在LaravelThinkPHPYii等主流框架中,可以直接使用对应的扩展,拿到决策器的Facade即可。

这里使用basic_model作为演示:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

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

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

接着是实例化决策器:

<?php

require_once './vender/autoload.php';

use Casbin\Enforcer;

$enforcer = new Enforcer('path/to/basic_model.conf');

自定义函数

使用已经实例化的决策器Enforcer,调用添加函数的方法,传入方法名和方法体即可。

假设,我们需要一个检查是否是超级管理员的方法,在方法里实现,如果是超级管理就返回true,在权限决策时,如果是超级管理员,则需要放行所有权限。

那么,我们需要修改basic_modelmatchers表达式:

[matchers]
m = checkIsAdmin(r.sub) || (r.sub == p.sub && r.obj == p.obj && r.act == p.act)

这里checkIsAdmin就是一个自定函数,传入请求中的sub参数,返回一个bool结果。从上面的表达式m中就可以看出,如果checkIsAdmin(r.sub)返回true,就不会执行后面的表达式,即达到了超级管理员,则需要放行所有权限的要求。

接下来,就是来实现这个自定义函数checkIsAdmin:

$enforcer->addFunction('checkIsAdmin', function(string $sub): bool {
    // 假设如果传入的 sub 等于 root ,即认为是超级管理员
    return $sub === 'root';
});

验证

上面我们添加了判断是否超级管理员的自定义函数,这里来验证一下结果。

$res = $enforcer->enforce('aclie', 'data', 'read');
var_dump($res); // false

$res = $enforcer->enforce('root', 'data', 'read');
var_dump($res); // true

看到上面的验证,如果传入的第一个参数subroot,就返回true,就实现超级管理员放行所有权限的要求。

最后

通过这个例子,主要介绍了在PHP-Casbin中通过自定义函数,实现不一样的权限决策逻辑。可以看出,这个自定义函数的功能还是非常实用的。当我们在实际项目中,遇到需要修改权限校验逻辑的时候,并不需要过多的侵入已有的代码,就可以很方便的快速的做出修改。