我正在使用Voters来限制对REST API中实体的访问。
考虑一下这个限制用户访问博客帖子的选民:
class BlogPostVoter extends Voter
{
public function __construct(AccessDecisionManagerInterface $decisionManager)
{
$this->decisionManager = $decisionManager;
}
/**
* Determines if the attribute and subject are supported by this voter.
*
* @param string $attribute An attribute
* @param int $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
*
* @return bool True if the attribute and subject are supported, false otherwise
*/
protected function supports($attribute, $subject)
{
if (!in_array($attribute, $this->allowedAttributes)) {
return false;
}
if (!$subject instanceof BlogPost) {
return false;
}
return true;
}
/**
* Perform a single access check operation on a given attribute, subject and token.
*
* @param string $attribute
* @param mixed $subject
* @param TokenInterface $token
* @return bool
* @throws \Exception
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
return $this->canUserAccess($attribute, $subject, $token);
}
public function canUserAccess($attribute, $subject, TokenInterface $token) {
if ($this->decisionManager->decide($token, array('ROLE_SUPPORT', 'ROLE_ADMIN'))) {
return true;
}
//other logic here omitted ...
return false;
}
}
您可以看到有一个公共函数canUserAccess
来确定是否允许用户查看BlogPost。这一切都很好。
现在我有另一个选民来检查其他内容,但也需要检查BlogPosts的这个相同的逻辑。我的想法是:
所以我想我会将BlogPostVoter注入我的其他选民:
class SomeOtherVoter extends Voter
{
public function __construct(BlogPostVoter $blogPostVoter)
{
$this->decisionManager = $decisionManager;
}
...
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
//other logic
if ($this->blogPostVoter->canUserAccess($attribute, $subject, $token)) {
return true;
}
return false;
}
}
当我这样做时,我使用setter和构造函数注入得到以下错误:
检测到服务的循环引用" security.access.decision_manager",路径:" security.access.decision_manager"
我不知道security.access.decision_manager
应该依赖于选民的实施。所以我没有看到循环引用的位置。
我还有另一种方式可以从VoterB呼叫VoterA吗?
答案 0 :(得分:1)
要引用VoterOne
中的VoterTwo
,您可以将AuthorizationCheckerInterface
注入VoterTwo
中,然后调用->isGranted('ONE')
。其中ONE是VoterOne
的受支持属性。
赞:
class VoterTwo extends Voter
{
private $authorizationChecker;
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
protected function supports($attribute, $subject)
{
return in_array($attribute, ['TWO']);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
return $this->authorizationChecker->isGranted('ONE', $subject);
}
}
在此示例中,VoterTwo
只是将请求重定向到VoterOne
(或支持属性ONE的投票者)。然后可以通过附加条件来扩展它。