Casbin多策略RBAC与ABAC共存时enforce调用报错及规则匹配问题
Casbin多策略RBAC+ABAC配置执行问题解决
问题重现
使用Casbin官方多策略示例配置RBAC与ABAC混合权限控制,模型与策略文件如下:
模型文件 multiple_policy_definitions_model.conf
[request_definition] r = sub, obj, act r2 = sub, obj, act [policy_definition] p = sub, obj, act p2= sub_rule, obj, act, eft [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] #RBAC m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act #ABAC m2 = eval(p2.sub_rule) && r2.obj == p2.obj && r2.act == p2.act
策略文件 multiple_policy_definitions_policy.csv
p, data2_admin, data2, read p2, r2.sub.Age > 18 && r2.sub.Age < 60, /data1, read, allow p2, r2.sub.Age > 60 && r2.sub.Age < 100, /data1, read, deny g, alice, data2_admin
执行以下代码时触发报错:
const { query } = request; // query = {Age:20} const result = await e.enforce(query, '/data1', 'read'); console.log(result);
报错信息:
TypeError: Cannot convert object to primitive value at Array.join (<anonymous>) at Array.toString (<anonymous>) at D:\mandy\Project\e_shopping_api\node_modules\casbin\lib\cjs\util\builtinOperators.js:286:26 at D:\mandy\Project\e_shopping_api\node_modules\expression-eval\dist\expression-eval.js:1:519 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Object.generatorRunAsync (D:\mandy\Project\e_shopping_api\node_modules\casbin\lib\cjs\util\util.js:160:26) at async Object.handler (D:\mandy\Project\e_shopping_api\src\routes\root.js:81:20)
问题原因
- 默认匹配器不匹配:
enforce()方法默认使用模型中定义的r请求规则和m匹配器,而m中包含RBAC的角色匹配逻辑g(r.sub, p.sub),但传入的sub是对象{Age:20},g函数需要字符串类型的角色标识,导致对象转字符串时抛出类型错误。 - 策略生效范围不足:原模型的
policy_effect仅判断p策略的allow,未包含p2策略的生效逻辑,即使触发m2匹配也无法正确返回权限结果。
解决方案
1. 调整模型的策略生效规则
修改[policy_effect]部分,让它同时考虑p和p2的权限结果:
[policy_effect] e = some(where (p.eft == allow || p2.eft == allow))
2. 明确指定使用ABAC匹配器
使用Casbin的enforceExplicitWithMatcher()方法,显式指定使用m2匹配器,对应r2请求规则:
const { query } = request; // 显式指定使用m2匹配器执行ABAC规则校验 const result = await e.enforceExplicitWithMatcher("m2", query, '/data1', 'read'); console.log(result); // 应返回true
补充:混合RBAC与ABAC的通用匹配器
如果需要同时支持RBAC(字符串sub)和ABAC(对象sub)的请求,可以合并匹配器逻辑,避免每次指定匹配器:
[matchers] m = (g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act) || (eval(p2.sub_rule) && r.obj == p2.obj && r.act == p2.act)
此时直接使用enforce()即可自动适配两种场景:
- 当
sub为字符串(如alice)时,走RBAC规则; - 当
sub为对象(如{Age:20})时,走ABAC规则。
验证
调整后,传入{Age:20}请求/data1的read权限,会触发p2的r2.sub.Age >18 && <60规则,返回true;若传入{Age:70},则触发deny规则,返回false。
内容的提问来源于stack exchange,提问作者Chen Mandy
相关产品推荐
相关产品推荐

