只需检查:从Symfony中投弃权票AbstractVoter isGranted

时间:2015-01-30 09:50:15

标签: php security symfony

我正在研究一个我们想要介绍Security Voters的Symfony2应用程序。 DX计划(jay!)给我们the simpler version这个机制,所以我想用它。唯一困扰我使用\Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter的事实是,在实施抽象isGranted方法时,我再也不能投弃权票了。我想为我们的应用程序更改它,但从安全的角度来看,我非常感谢您对此事的看法。

要明确的是,在我们的应用程序中,我们将使用unanimous访问决策经理策略 - 简而言之:您至少需要一个ACCESS_GRANTED而不是ACCESS_DENIED - 因为我们可能会在以后想引入选民禁止IP地址或其他恶作剧。

如下面的相关代码段所示,只要AbstractVoter的实施支持某个属性,投票就会默认为Denied

public function vote(TokenInterface $token, $object, array $attributes)
{
    if (!$object || !$this->supportsClass(get_class($object))) {
        return self::ACCESS_ABSTAIN;
    }

    // abstain vote by default in case none of the attributes are supported
    $vote = self::ACCESS_ABSTAIN;

    foreach ($attributes as $attribute) {
        if (!$this->supportsAttribute($attribute)) {
            continue;
        }

        // as soon as at least one attribute is supported, default is to deny access
        $vote = self::ACCESS_DENIED;

        if ($this->isGranted($attribute, $object, $token->getUser())) {
            // grant access as soon as at least one voter returns a positive response
            return self::ACCESS_GRANTED;
        }
    }

    return $vote;
}

我想要做的是使用下面的代码覆盖

public function vote(TokenInterface $token, $object, array $attributes)
{
    if (!$object || !$this->supportsClass(get_class($object))) {
        return self::ACCESS_ABSTAIN;
    }

    $vote = self::ACCESS_ABSTAIN;

    foreach ($attributes as $attribute) {
        if (!$this->supportsAttribute($attribute)) {
            continue;
        }

        // This is where we differ from SymfonyAbstractVoter. Only if there is an outspoken yes or no, a vote is cast
        // When returning null, it will still abstain
        $grant = $this->isGranted($attribute, $object, $token->getUser());
        if ($grant === true) {
            return self::ACCESS_GRANTED;
        }
        if($grant === false) {
            return self::ACCESS_DENIED;
        }

    }

    return $vote;
}
你怎么看?从ACCESS_ABSTAIN返回null时返回isGranted是否安全,如果投票人返回true或false,则只投出ACCESS_GRANTEDACCESS_DENIED


为什么我甚至想要这样做?仍然使用AbstractVoter(因为,是的,我是一个懒惰的开发人员),但我分开了我的顾虑。

让我们说我为一个帖子PostVoter做了一个选民,这将允许我编辑自己的帖子。然后它将投射ACCESS_GRANTED。但只要我不拥有这个帖子,这个选民真的不在乎:它应该只投一个ACCESS_ABSTAIN。 稍后它可能会遇到AdminVoter,但仍然会投放ACCESS_GRANTED。 但是,在使用unanimous访问权限决策经理策略时,如果此PostVoter已经投放了ACCESS_DENIED,那么它将永远不会获得任何其他选民。

我现在无法在ACCESS_ABSTAIN中投放AbstractVoter vote而不会覆盖{{1}}方法,而在我看来,更简单的选民的全部观点就是制作它更简单:)

1 个答案:

答案 0 :(得分:1)

AbstractVoter类是大多数用例的简单引导实现,它模拟了internal voters behave的方式,因此只要您认为您的解决方案与基本情况下,您可以随意使用自己的方法覆盖。