我用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;
}
}
问题:
减少对voter::vote()的调用
我的投票者被包括在每一个页面加载中并被调用。即使他们不支持给定类的决策。
FoobarVoter::vote()
总是被调用。即使FoobarVoter::supportsClass()
或FoobarVoter::supportsAttribute
返回false。因此,我需要检查FoobarVoter::vote()
中的类和属性。这种行为规范吗?我怎样才能避免这个不必要的电话。限制选民人数
一些投票者只需要在特定的组合中。有些只需要决定特定的类。因此,在我的申请书的所有部分并不需要一些选民。是否可以动态地包含每个包/实体的投票者?例如,只有在访问/使用特定捆绑包或特定实体时,才将投票者包括在决策管理链中?
最佳答案
纵观symfony的源代码,似乎是因为AccessDecisionManager
使用这些方法(supportsclass和seupportsattribute)将支持汇总到自身。
这允许您的投票者做的是在应用管理器时扩展案例。所以你没有详细说明你的选民的能力,而是整个投票过程。不管你想要的是不是别的…
至于减少不必要的电话,在一般情况下是不必要的。系统采用以下三种方法之一进行设计:
基于允许(decideAffirmative
)。这使用“基于允许”的投票。这意味着如果一个插件说“允许”,那么你就被允许了。
基于consensus的(decideConsensus
)。这使用了一个基于同意的许可,如果更多的选民同意而不是否认你被允许…
基于拒绝(decideUnanimous
)。这使用“基于拒绝”的投票。这意味着如果一个插件说“拒绝”,那么你就被拒绝了。否则你至少需要一笔补助金。
因此,考虑到它们都依赖于显式的deny vs allow,为每个请求运行所有插件实际上是有意义的。因为即使您不特别支持某个类,您也可能希望允许或拒绝该请求。
简而言之,通过限制选民的支持度来获得的好处并不多。