Symfony 2 acl isFieldGranted抛出异常

时间:2013-10-15 16:44:51

标签: symfony acl symfony-2.3

我正在我的应用程序中忙于在Class + Field(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";
}

而不是返回false,$ acl-> isFieldGranted会抛出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

1 个答案:

答案 0 :(得分:0)

您似乎必须在代码中捕获NoAceFoundException并抛出AccessDeniedException

try{
    if (!$acl->isFieldGranted('name', $masks, $sids)) {
        throw new Symfony\Component\Security\Core\Exception\AccessDeniedException();
    } 
} catch (NoAceFoundException $e) {
    throw new Symfony\Component\Security\Core\Exception\AccessDeniedException();
}

由于:

  

第一个适用的ACE将作出最终决定   许可/身份组合。如果它是授予,这种方法将   返回true,如果是否认,该方法将继续检查   下一个许可/身份组合。重复该过程   直到找到授予ACE,或者没有许可/身份   留下了组合。最后,我们要么抛出一个   NoAceFoundException,或拒绝访问。

因此,如果找不到MaskBuilder::MASK_OWNER/RoleSecurityIdentity($role)组合,则会抛出NoAceFoundException。有关详细信息,请参阅this第137行。