Reputation: 2507
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.
Upvotes: 1
Views: 1451
Reputation: 2507
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
Upvotes: 1
Reputation: 9362
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.
Upvotes: 1