【发布时间】:2013-10-15 16:44:51
【问题描述】:
我正忙于在我的应用程序中实现类 + 字段 (classFieldAce) 级别的 ACL。一切似乎都运行良好,但我从 ACL 的 isFieldGranted() 方法中得到了意外的行为。这是我的代码:
// setup ACL
$className = 'Acme\Model\Junk';
$oid = new ObjectIdentity('class', $className);
try {
$acl = $aclProvider->findAcl($oid);
} catch (Exception $e) {
$acl = $aclProvider->createAcl($oid);
$roleUser = new RoleSecurityIdentity('ROLE_USER');
$mask = new MaskBuilder(4); // 4 = EDIT
$acl->insertclassFieldAce('name', $roleUser, $mask->get());
}
$aclProvider->updateAcl($acl);
到目前为止一切顺利。我将角色“ROLE_USER”分配给我的用户。现在我想运行一些检查(在我创建服务时手动)。这是检查代码(目前在控制器内部):
// check the ACL
$className = 'Acme\Model\Junk';
$oid = new ObjectIdentity('class', $className);
$aclProvider = $this->get('security.acl.provider');
try {
$acl = $aclProvider->findAcl($oid);
} catch (...)
一切都好。现在我要检查的东西:
$sids = array();
foreach ($this->getUser()->getRoles() as $role) {
$sids[] = new RoleSecurityIdentity($role);
}
$masks = array();
$masks[] = MaskBuilder::MASK_EDIT;
if ($acl->isFieldGranted('name', $masks, $sids)) {
echo "OK";
} else {
echo "NOT ALLOWED";
}
此时一切正常,我得到输出“OK”。我唯一不确定的是将 $sids 发送到支票的非常迂回的方式 - 所以我的第一个问题是除了手动构建列表之外是否有更快的方式。
当我尝试检查更高的掩码时,事情开始出现“错误”(如意料之外):
$sids = array();
foreach ($this->getUser()->getRoles() as $role) {
$sids[] = new RoleSecurityIdentity($role);
}
$masks = array();
$masks[] = MaskBuilder::MASK_OWNER;
if ($acl->isFieldGranted('name', $masks, $sids)) {
echo "OK";
} else {
echo "NOT ALLOWED";
}
$acl->isFieldGranted 不是返回 false,而是抛出 NoAceFoundException。
我是否以错误的方式进行现场检查,还是应该在这里捕获异常?
更新:添加日志:
校验码改为:
$this->get('logger')->debug('XX: ACL retrieved, checking field grants');
try {
if ($acl->isFieldGranted('name', $masks, $sids, true)) {
$this->get('logger')->debug('XX: ACL OK for field :name:');
}
} catch (NoAceFoundException $e) {
$this->get('logger')->debug('XX: ACL NOT OK for field :name: NoAceFoundException thrown');
}
检查成功后,日志如下:
DEBUG - SELECT o.id as acl_id, o.object_identifier, o.parent_object_identity_id,
o.entries_inheriting, c.class_type, e.id as ace_id, e.object_identity_id, e.field_name,
e.ace_order, e.mask, e.granting, e.granting_strategy, e.audit_success, e.audit_failure,
s.username, s.identifier as security_identifier FROM acl_object_identities o INNER JOIN
acl_classes c ON c.id = o.class_id LEFT JOIN acl_entries e ON ( e.class_id = o.class_id AND
(e.object_identity_id = o.id OR e.object_identity_id IS NULL) )
LEFT JOIN acl_security_identities s ON ( s.id = e.security_identity_id ) WHERE (o.id =16)
DEBUG - SELECT t0.name AS name1, t0.roles AS roles2, t0.id AS id3 FROM staff_group t0
INNER JOIN rel_staff_staff_group ON t0.id = rel_staff_staff_group.group_id
WHERE rel_staff_staff_group.staff_id = ? Context: ["242"]
DEBUG - XX: ACL retrieved, checking field grants
DEBUG - XX: ACL OK for field :name:
检查失败时,唯一的变化是这一行(我比较了两个浏览器标签中的日志)
DEBUG - XX: ACL NOT OK for field :name: NoAceFoundException thrown
在日志记录方面没有区别
$acl->isFieldGranted('name', $masks, $sids)
和
$acl->isFieldGranted('name', $masks, $sids, true)
更新 2:
我在 Symfony 中打开了一个错误报告并已解决 https://github.com/symfony/symfony/issues/9433
【问题讨论】:
-
@freetrace 感谢您的建议;更新的问题,但没有从日志中得到太多
-
好的。尝试在您的
$acl->isFieldGranted('name', $masks, $sids)之前插入此var_dump($acl->getClassFieldAces('name'));。 -
会不会是ACL系统的bug?
-
确实是个bug,我更新了问题
标签: symfony acl symfony-2.3