Question

I want to secure all urls that have the ?preview=true query string applied. The following unfortunately does not work. I guess the request matcher looks at pathInfo only.

# app/config/security.yml
access_control:
    - { path: (?|&)preview=true, role: ROLE_ADMIN }

Any hints are much appreciated.

Was it helpful?

Solution 2

Solved it myself. As @Chausser said access control via query params is not possible in security.yml, so I've created a voter for that.

// src/Your/Bundle/Security/Voter/PreviewAccessVoter.php
namespace Your\Bundle\Security\Voter;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;


/**
 * voter that denies access if user has not the required role
 * to access urls with preview query param set true
 */
class PreviewAccessVoter implements VoterInterface
{

    protected $requestStack;
    protected $requiredRole;


    public function __construct(RequestStack $requestStack, $requiredRole)
    {
        $this->requestStack  = $requestStack;
        $this->requiredRole = $requiredRole;
    }


    public function supportsAttribute($attribute)
    {
        return true;
    }


    public function supportsClass($class)
    {
        return true;
    }


    public function vote(TokenInterface $token, $object, array $attributes)
    {
        if(filter_var($this->requestStack->getCurrentRequest()->query->get('preview'), FILTER_VALIDATE_BOOLEAN))
        {
            foreach($token->getRoles() as $role) {
                if($this->requiredRole === $role->getRole()) {
                    return VoterInterface::ACCESS_GRANTED;
                }
            }
            return VoterInterface::ACCESS_DENIED;
        }

        return VoterInterface::ACCESS_ABSTAIN;
    }
}

Add voter as (hidden) service

# src/Your/Bundle/Resources/config/services.yml
# preview voter that denies access for users without the required role
security.access.preview.voter:
    class:      Your\BundleBundle\Security\Voter\PreviewAccessVoter
    arguments:  [ @request_stack , ROLE_ADMIN ]
    tags:       [ { name: security.voter } ]
    public:     false

Changing the Access Decision Strategy

# app/config/security.yml
access_decision_manager:
    strategy: unanimous # can be: affirmative, unanimous or consensus


see: http://symfony.com/doc/current/cookbook/security/voters.html as a reference
https://github.com/symfony/Security/blob/master/Core/Authorization/Voter/RoleVoter.php might also be helpful

OTHER TIPS

Im pretty sure that access control only looks at the hierarchical part and not the query string. This is because query parameters are not meant to determine content, only to be filters on content. You will likely need to rework your URL structure to match these.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top