我遇到了类范围的问题。我为a创造了一个王牌 像这样的课:
$userIdentity = UserSecurityIdentity::fromAccount($user);
$classIdentity = new ObjectIdentity('some_identifier', 'Class\FQCN');
$acl = $aclProvider->createAcl($classIdentity);
$acl->insertClassAce($userIdentity, MaskBuilder::MASK_CREATE);
$aclProvider->updateAcl($acl);
现在,我正在尝试检查用户的权限。我发现了这种方式 做事情,没有记录,但给出了预期 课程结果:
$securityContext->isGranted('CREATE', $classIdentity); // returns true
$securityContext->isGranted('VIEW', $classIdentity); // returns true
$securityContext->isGranted('DELETE', $classIdentity); // returns false
此方法很好地适应了“CREATE”权限检查,其中 没有可用的对象实例传递给该方法。然而, 应该可以检查是否授予了另一个权限 特定实例基础:
$entity = new Class\FQCN();
$em->persist($entity);
$em->flush();
$securityContext->isGranted('VIEW', $entity); // returns false
这是测试失败的地方。我期望有一个给定的用户 一个类上的权限掩码对每个都具有相同的权限 该类的实例,如文档中所述(“The 如果,PermissionGrantingStrategy首先检查所有对象范围的ACE none是适用的,类范围的ACE将被检查“),但它 似乎并非如此。
答案 0 :(得分: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;
}
}
然后在security.yml中设置:
jms_security_extra:
voters:
disable_acl: true
最后将选民设置为服务:
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 }
答案 1 :(得分:5)
您需要确保每个对象都有自己的ACL(使用$aclProvider->createAcl($entity)
)才能使类范围权限正常工作。
请参阅此讨论:https://groups.google.com/forum/?fromgroups=#!topic/symfony2/pGIs0UuYKX4
答案 2 :(得分: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();
}
这应该有用!
如果你要检查“对象范围”,你可以在isGranted函数调用中使用$ post而不是$ objectIdentity。
答案 3 :(得分:0)
我试图找到解决这个问题的最佳解决方案,我认为最好的答案是Bart的rryter /编辑。我只是想扩展解决方案。
假设您要为特定用户授予特定对象类型的访问权限,但不能访问具体对象实例(例如id = 1)。
然后您可以执行以下操作:
$aclProvider = $this->get('security.acl.provider');
$objectIdentity = new ObjectIdentity('class', 'someNamspace\\SeperatedByDoubleSlashes');
$acl = $aclProvider->createAcl($objectIdentity);
// retrieving the security identity of the currently logged-in user
$securityContext = $this->get('security.context');
$user = $securityContext->getToken()->getUser();
$securityIdentity = UserSecurityIdentity::fromAccount($user);
// grant owner access
$acl->insertObjectAce($securityIdentity, MaskBuilder::MASK_OWNER);
$aclProvider->updateAcl($acl);
$securityContext = $this->get('security.context');
// check for edit access
if (false === $securityContext->isGranted('EDIT', $objectIdentity)) {
throw new AccessDeniedException();
}
与symfony cookbook给出的示例的不同之处在于您使用的是类范围,而不是对象范围。 只有一条线有所不同:
$objectIdentity = new ObjectIdentity('class', 'someNamspace\\SeperatedByDoubleSlashes');
而不是:
$objectIdentity = ObjectIdentity::fromDomainObject($object);
如果您的类acl中至少有一个类范围权限,您仍然可以为特定对象实例添加特定权限。