为什么总是打电话给symfony2安全选民?

时间:2013-03-21 15:30:29

标签: php performance security symfony

我使用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()内的类和属性。这个行为标准是什么?我该如何防止这种不必要的电话。

限制选民捆绑

某些选民只需要在特定的捆绑内部。有些人只需要决定具体的课程。因此,在我的申请的所有部分都不需要一些选民。是否可以动态地包括每个捆绑/实体的选民?例如如果访问/使用特定的捆绑包或特定实体,则只包括选民进入决策管理链?

1 个答案:

答案 0 :(得分:8)

查看Symfony的源代码,似乎是因为AccessDecisionManager使用这些方法(supportsClass和seupportsAttribute)来支持自身。

这允许您的选民做的是在应用经理时扩展案例。因此,您没有详细说明您的选民的能力,而是详细说明整个投票过程的能力。这是否是你想要的东西......

就减少不必要的呼叫而言,在一般情况下并非必要。系统使用以下三种方法之一进行设计:

  1. 允许基于decideAffirmative)。这使用“基于允许”的投票。这意味着如果一个插件说“允许”,那么你就被允许了。

  2. 基于共识decideConsensus)。这使用基于共识的许可,如果更多的选民同意允许而不是否认你被允许...

  3. 拒绝decideUnanimous)。这使用“基于拒绝”的投票。这意味着如果一个插件说“拒绝”,那么你就被拒绝了。否则你至少需要一笔补助金。

  4. 因此,考虑到所有这些都依赖于显式Deny vs Allow,为每个请求运行所有插件实际上是有意义的。因为即使您没有专门支持某个类,您也可能希望允许或拒绝该请求。

    简而言之,通过支持属性限制选民并没有多少收获。