我使用security voters作为symfony的acl系统的替代品。
我的选民看起来与以下类似。
class FoobarVoter implements VoterInterface
{
public function supportsClass($class)
{
return in_array($class, array(
'Example\FoobarBundle\Entity\Foobar',
));
}
public function supportsAttribute($attribute)
{
return in_array(strtolower($attribute), array('foo', 'bar'));
}
public function vote(TokenInterface $token, $object, array $attributes)
{
$result = VoterInterface::ACCESS_ABSTAIN
if (!$this->supportsClass(get_class($object))) {
return VoterInterface::ACCESS_ABSTAIN;
}
foreach ($attributes as $attribute) {
$attribute = strtolower($attribute);
// skip not supported attributes
if (!$this->supportsAttribute($attribute)) {
continue;
}
[... some logic ...]
}
return $result;
}
}
我的选民被包含在每个页面加载中并被调用。即使他们不支持给定班级的决定。始终会调用FoobarVoter::vote()
。即使FoobarVoter::supportsClass()
或FoobarVoter::supportsAttribute
返回false。因此我需要检查FoobarVoter::vote()
内的类和属性。这个行为标准是什么?我该如何防止这种不必要的电话。
答案 0 :(得分:8)
查看Symfony的源代码,似乎是因为AccessDecisionManager
使用这些方法(supportsClass和seupportsAttribute)来支持自身。
这允许您的选民做的是在应用经理时扩展案例。因此,您没有详细说明您的选民的能力,而是详细说明整个投票过程的能力。这是否是你想要的东西......
就减少不必要的呼叫而言,在一般情况下并非必要。系统使用以下三种方法之一进行设计:
允许基于(decideAffirmative
)。这使用“基于允许”的投票。这意味着如果一个插件说“允许”,那么你就被允许了。
基于共识(decideConsensus
)。这使用基于共识的许可,如果更多的选民同意允许而不是否认你被允许...
拒绝(decideUnanimous
)。这使用“基于拒绝”的投票。这意味着如果一个插件说“拒绝”,那么你就被拒绝了。否则你至少需要一笔补助金。
因此,考虑到所有这些都依赖于显式Deny vs Allow,为每个请求运行所有插件实际上是有意义的。因为即使您没有专门支持某个类,您也可能希望允许或拒绝该请求。
简而言之,通过支持属性限制选民并没有多少收获。