如何在Symfony2中使用类范围的aces?

Ste*_*efk 11 acl symfony

我有类范围的问题.我为这样的类创建了一个ace:

$userIdentity = UserSecurityIdentity::fromAccount($user);
$classIdentity = new ObjectIdentity('some_identifier', 'Class\FQCN');
$acl = $aclProvider->createAcl($classIdentity);
$acl->insertClassAce($userIdentity, MaskBuilder::MASK_CREATE);
$aclProvider->updateAcl($acl);
Run Code Online (Sandbox Code Playgroud)

现在,我正在尝试检查用户的权限.我找到了这种做事方式,没有记录,但是在课堂上给出了预期的结果:

$securityContext->isGranted('CREATE', $classIdentity);  // returns true
$securityContext->isGranted('VIEW', $classIdentity);    // returns true
$securityContext->isGranted('DELETE', $classIdentity);  // returns false
Run Code Online (Sandbox Code Playgroud)

此方法很好地适应"CREATE"权限检查,其中没有可用的对象实例传递给该方法.但是,应该可以检查是否在特定实例的基础上授予了另一个权限:

$entity = new Class\FQCN();
$em->persist($entity);
$em->flush();
$securityContext->isGranted('VIEW', $entity);  // returns false
Run Code Online (Sandbox Code Playgroud)

这是测试失败的地方.我希望在类上具有给定权限掩码的用户对该类的每个实例具有相同的权限,如文档中所述("PermissionGrantingStrategy首先检查所有对象范围的ACE,如果没有适用的话,该类-scope ACE将被检查"),但似乎并非如此.

小智 6

你做得对.并根据本页底部,它应该工作,但它没有.

使其工作的最简单方法是创建一个AclVoter类:

namespace Core\Security\Acl\Voter;

use JMS\SecurityExtraBundle\Security\Acl\Voter\AclVoter as BaseAclVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Doctrine\Common\Util\ClassUtils;

class AclVoter extends BaseAclVoter
{
    public function vote( TokenInterface $token , $object , array $attributes )
    {   
    //vote for object first
    $objectVote =   parent::vote( $token , $object , $attributes ); 

    if( self::ACCESS_GRANTED === $objectVote )
    {
        return self::ACCESS_GRANTED;
    }
    else
    {
        //then for object's class
        $oid    =   new ObjectIdentity( 'class' , ClassUtils::getRealClass( get_class( $object ) ) );
        $classVote  =   parent::vote( $token , $oid , $attributes );                

        if( self::ACCESS_ABSTAIN === $objectVote )
        {       
        if( self::ACCESS_ABSTAIN === $classVote )
        {          
            return self::ACCESS_ABSTAIN;
        }
        else
        {
            return $classVote;
        }
        }
        else if( self::ACCESS_DENIED === $objectVote )
        {
        if( self::ACCESS_ABSTAIN === $classVote )
        {
            return self::ACCESS_DENIED;
        }
        else
        {
            return $classVote;
        }
        }       
    }

    return self::ACCESS_ABSTAIN;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在security.yml中设置:

jms_security_extra:
    voters:
        disable_acl: true  
Run Code Online (Sandbox Code Playgroud)

最后将选民设置为服务:

core.security.acl.voter.basic_permissions:
    class: Core\Security\Acl\Voter\AclVoter
    public: false
    arguments: 
      - '@security.acl.provider'
      - '@security.acl.object_identity_retrieval_strategy'
      - '@security.acl.security_identity_retrieval_strategy'
      - '@security.acl.permission.map' 
      - '@?logger'   
    tags:
        - { name: security.voter , priority: 255 }           
        - { name: monolog.logger , channel: security }    
Run Code Online (Sandbox Code Playgroud)


Sal*_*bas 5

您需要确保每个对象都有自己的ACL(使用$aclProvider->createAcl($entity)),以使类范围权限正常工作.

请参阅此讨论:https://groups.google.com/forum/?fromgroups =#!topic / symfony2/pGIs0UuYKX4


rry*_*ter 2

如果您没有现有实体,您可以检查您创建的 objectIdentity。请小心使用“双反斜杠”,因为反斜杠会转义。

$post = $postRepository->findOneBy(array('id' => 1));

$securityContext = $this->get('security.context');
$objectIdentity = new ObjectIdentity('class', 'Liip\\TestBundle\\Entity\\Post');

// check for edit access
if (true === $securityContext->isGranted('EDIT', $objectIdentity)) {
    echo "Edit Access granted to: <br/><br/> ";
    print_r("<pre>");
    print_r($post);
    print_r("</pre>");
} else {
    throw new AccessDeniedException();
}
Run Code Online (Sandbox Code Playgroud)

那应该有效!

如果您要检查“对象范围”,您可以在 isGranted 函数调用中使用 $post 而不是 $objectIdentity 。