Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are symfony2 security voters always called?

I am using security voters as alternative to symfony's acl system.

example voter:

my voters look similar go the following one.

    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;
        }
    }

questions:

reduce calls to Voter::vote()

my voters are included and called on every page load. even if they do not support decisions for a given class. FoobarVoter::vote() is always called. even if FoobarVoter::supportsClass() or FoobarVoter::supportsAttribute return false. thus i need to check class and attribute inside FoobarVoter::vote(). is this behaviour standard? how can i prevent this unnecessary call.

limit voters to bundles

some voters are only needed inside specific bundles. some are only needed to decide about specific classes. thus some voters are not needed in all parts of my application. is it possible to include voters per bundle/entity dynamically? e.g. only include voters into decision manager chain if a specific bundle or a specific entity is accessed/used?

like image 451
Martin Abraham Avatar asked Mar 21 '13 15:03

Martin Abraham


People also ask

What is Symfony voter?

Voters are Symfony's most powerful way of managing permissions. They allow you to centralize all permission logic, then reuse them in many places.

Is Symfony secure?

Symfony provides many tools to secure your application. Some HTTP-related security tools, like secure session cookies and CSRF protection are provided by default. The SecurityBundle, which you will learn about in this guide, provides all authentication and authorization features needed to secure your application.


1 Answers

Looking through the source code of Symfony, it appears to be because the AccessDecisionManager uses those methods (supportsClass and seupportsAttribute) to roll-up support to itself.

What this allows your voter to do is extend the cases when the manager will be applied. So you're not detailing the capability of your voter, but of the entire voting process. Whether or not that's what you want is something else...

As far as reducing the un-necessary calls, it's not un-necessary in the general case. The system is designed using one of three methods:

  1. Allow based (decideAffirmative). This uses an "allow based" voting. Which means that if one plugin says "allow" then you're allowed.

  2. Concensus Based (decideConsensus). This uses a concensus based permission, where if more voters agree to allow than to deny you're allowed...

  3. Deny Based (decideUnanimous). This uses a "deny based" voting. Which means that if one plugin says "deny", then you're denied. Otherwise you need at least one grant.

So considering that all of them rely on the explicit Deny vs Allow, running all of the plugins for every request actually makes sense. Because even if you don't specifically support a class, you may want to allow or deny that request.

In short, there's not much to gain by limiting the voters by the supports attributes.

like image 66
ircmaxell Avatar answered Sep 30 '22 15:09

ircmaxell