我正在尝试创建一个自定义选民来检查实体的访问权限以执行特定操作。因此,其逻辑运行良好。但是,如果用户是该实体的“所有者”,或者他们是管理员,那么我有一些允许的操作。
但是,我不能只检查用户的角色,因为我正在查看角色层次结构。文档中的示例仅使用 in_array
,但这不起作用(http://symfony.com/doc/current/best_practices/security.html)
我的选民是这样的(为了清楚起见,缩短了)。我已经尝试注入(inject)安全上下文(或者特别是 2.6 中的 AuthorizationCheckerInterface),但是由于这是一个投票者,所以它具有循环依赖关系。
<?php
// ...
class ApplicationVoter extends AbstractVoter
{
const VIEW = 'view';
/**
* @var AuthorizationCheckerInterface
*/
private $security;
/*public function __construct(AuthorizationCheckerInterface $security)
{
$this->security = $security;
}*/
/**
* {@inheritdoc}
*/
protected function getSupportedAttributes()
{
return array(
self::VIEW
);
}
/**
* {@inheritdoc}
*/
protected function getSupportedClasses()
{
return array('Study\MainBundle\Entity\Application');
}
/**
* {@inheritdoc}
*/
protected function isGranted($attribute, $application, $user = null)
{
if (!$user instanceof UserInterface) {
return false;
}
if ($attribute === self::VIEW) {
return $this->canView($application, $user);
}
return false;
}
/**
* Can view own application if not deleted
* Admin can view if submitted
*
* @param \Study\MainBundle\Entity\Application $application
* @param \Study\MainBundle\Entity\User $user
*
* @return boolean
*/
protected function canView(Application $application, User $user)
{
return ($application->isOwner($user) && !$application->isDeleted())
|| (!$application->isHiddenToAdmin() && $this->security->isGranted('ROLE_ADMIN_RO'));
}
}
我想在这里只使用内置的 RoleHiarchyVoter,但它是一项非公共(public)服务。
有什么解决办法吗?如果可能的话,我想避免重复框架代码或使我的角色比字符串更复杂。
编辑:注入(inject)整个容器有效,但不是我理想的解决方案。这是我可以从选民那里访问内置层次结构的唯一方法吗?
最佳答案
有一个名为 security.role_hierarchy 的服务,其中包含您需要的信息。这基本上是安全上下文检查角色的方式。需要几行包装代码,但还不错。
# Need this because the service is not public
# http://symfony.com/doc/current/components/dependency_injection/advanced.html
cerad_core__role_hierarchy:
alias: security.role_hierarchy
cerad_game__game_official__voter:
class: Cerad\Bundle\GameBundle\Action\GameOfficial\GameOfficialVoter
public: false
arguments:
- '@cerad_core__role_hierarchy'
tags:
- { name: security.voter }
选民等级:
class GameOfficialVoter implements VoterInterface
{
public function __construct($roleHierarchy)
{
$this->roleHierarchy = $roleHierarchy;
}
protected function hasRole($token,$targetRole)
{
$reachableRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());
foreach($reachableRoles as $role)
{
if ($role->getRole() == $targetRole) return true;
}
return false;
}
protected function canViewOfficialName($official,$token)
{
// Pending is the only one protected against for now
if ($official->getAssignState() != 'Pending') return $this->accessGranted;
// Assignors can always see
if ($this->hasRole($token,'ROLE_ASSIGNOR')) return $this->accessGranted;
return $this->accessDenied;
}
}
关于Symfony2 自定义选民角色层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27328052/