为啥 symfony2 安全选民总是被召唤?

Posted

技术标签:

【中文标题】为啥 symfony2 安全选民总是被召唤?【英文标题】:Why are symfony2 security voters always called?为什么 symfony2 安全选民总是被召唤? 【发布时间】:2013-03-11 05:02:45 【问题描述】:

我正在使用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() 中的类和属性。这是行为标准吗?我怎样才能防止这种不必要的电话。

将投票者限制为捆绑包

一些选民只需要在特定的捆绑包中。有些只需要决定特定的类。因此,我的申请的所有部分都不需要一些选民。是否可以动态地包括每个捆绑/实体的选民?例如仅在访问/使用特定捆绑包或特定实体时才将选民纳入决策管理器链?

【问题讨论】:

Ad 1) 这是标准行为,因为您不需要限制选民的使用 - 在这种情况下调用这些方法会导致额外的过热。通过添加额外的检查,您只会增加过热。这一切都取决于选民的写作效率。广告 2) 并非如此。即使您能够对其进行一些优化,我怀疑这是否会带来值得投入时间的差异。 好吧,听起来和预期的一样。我唯一的想法是创建一个通用选民。这个选民将通过延迟加载实例化子选民。次级选民为单个实体做出决定。因此,每次页面加载时只检查一个选民。 似乎是个好主意。你能做点什么吗? 对不起,还没意识到。如果您在此处发布您的解决方案,那就太好了。一个 symfony 的人建议还是使用 symfony 的 acl。 【参考方案1】:

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

这允许您的选民做的是延长申请经理的案例。所以你不是在详细说明你的选民的能力,而是整个投票过程。不管那是不是你想要的,都是另一回事……

就减少不必要的调用而言,在一般情况下并不是不必要的。该系统是使用以下三种方法之一设计的:

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

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

    拒绝 (decideUnanimous)。这使用“基于拒绝”的投票。这意味着如果一个插件说“拒绝”,那么你就会被拒绝。否则,您至少需要一项赠款。

所以考虑到它们都依赖于明确的拒绝与允许,为每个请求运行所有插件实际上是有意义的。因为即使您不专门支持某个课程,您也可能希望允许或拒绝该请求。

简而言之,通过支持属性限制选民并没有什么好处。

【讨论】:

以上是关于为啥 symfony2 安全选民总是被召唤?的主要内容,如果未能解决你的问题,请参考以下文章

symfony2 选民或 acl

Symfony 2 ACL 与选民

将对象传递给自定义选民?

Symfony 2 安全总是返回 Bad Credentials 错误

symfony2 安全 - 禁用登录路径并显示禁止

Symfony2 安全不同的防火墙不能正确重定向到登录