CASL.js能否直接针对subject评估字段限制?
描述
我的目标是将req.body作为CASL.js的subject(通过内置的subject helper构建)进行评估,既要判断用户能否在预定义的conditions下对该subject执行操作,也要验证传入的req.body仅包含Ability构造函数的AbilityTuple中定义的允许fields。
我原本以为这是can()工具的默认功能,直到某次非常规使用中发现,只要conditions匹配,被评估的subject可以包含任何fields数组中未定义的额外字段。
示例说明
我在数据库的JSON中定义了一个用户权限(grant):
{ "action": "create", "subject": "users", "conditions": { "idPlatform": 8, "idRole": 14 }, "fields": [ "idPlatform", "idRole", "attributes.**", "key", "person.documents.**", "person.emails.**" ] }
该权限会与用户的其他权限一起传入new Ability()构造函数。随后,端点控制器会在执行后续方法前,通过ability.can()工具评估用户执行创建用户操作的权限,代码如下:
async authorize(req) { const userSubject = subject('users', req.body); if (!await this.ability.can('create', userSubject)) { throw new Error('Unauthorized'); } }
假设用户向该端点发送以下请求体:
{ idPlatform: 8, idRole: 14, key: "myusername", active: 0, person: { documents: [ { idType: 1, document: "37548323" }, { idType: 3, document: "20375483231" } ], emails: [ { idType: 2, email: "mypersonalemail@gmail.com" }, { idType: 3, email: "myworkemail" } ], telephones: [ { "idType": 1, "telephone": "29445368432" } ] } }
可以看到,请求体包含fields权限对象中未声明的两个额外字段:active和person.telephones。但由于请求体匹配了定义的两个conditions(idPlatform和idRole),ability.can()方法返回true。
我希望ability.can()工具还能评估提供的subject是否仅包含用户允许的字段,若存在额外字段则返回false。目前我可以通过将subject的键扁平化为字符串数组来实现:
['idPlatform', 'idRole', 'key', 'active', 'person.documents.idType', 'person.documents.document', ...]
随后遍历该数组,调用ability.can('create', subject, flattenedField)进行逐一检查。
内容的提问来源于stack exchange,提问作者Sebastián Sameghini

