I have some rules in security.yml that basically tell symfony which roles should be alowed to access some route/url. Is there a way to determine in the code for a given request which roles are allowed? I am intending to use this in an event listener.
CodePudding user response:
You can use AccessMap
from use Symfony\Component\Security\Http\AccessMapInterface;
AccessMap contain the mapping of your access_control configuration.
You can auto wire the service easily in your listener:
private AccessMapInterface $accessMap;
public function __construct(AccessMapInterface $accessMap)
{
$this->accessMap = $accessMap;
}
Don't forget to register the service :
#services.yaml
services:
#...
Symfony\Component\Security\Http\AccessMapInterface: '@security.access_map'
Then you can use AccessMap
to match your request using the method $this->accessMap->getPatterns($request)
and access each configuration.
Example from one of my projet:
Symfony\Component\Security\Http\AccessMap {#8567 ▼
-map: array:7 [▼
0 => array:3 [▼
0 => Symfony\Component\HttpFoundation\RequestMatcher {#8547 ▼
-path: "^/login"
-host: null
-port: null
-methods: []
-ips: []
-attributes: []
-schemes: []
}
1 => array:1 [▼
0 => "PUBLIC_ACCESS"
]
2 => null
]
1 => array:3 [▶]
2 => array:3 [▶]
3 => array:3 [▶]
4 => array:3 [▶]
5 => array:3 [▶]
6 => array:3 [▶]
]
}
Let's try to see what role is required in my login page:
//$request is from my login page
dump($this->accessMap->getPatterns($request));
array:2 [▼
0 => array:1 [▼
0 => "PUBLIC_ACCESS"
]
1 => null
]
So it should be easy to match your request in your listener, and use the result of getPatterns which contains the required roles for your request.
If you want to access a specific route configuration that is not your current request, you could do something like:
$this->accessMap->getPatterns(Request::create('/login', 'GET'));
CodePudding user response:
Yes u can do that with Voters https://symfony.com/doc/current/security/voters.html
CodePudding user response:
The way to check roles programmatically is through the Security service of the symfony container, or if you extend the AbstractController class in your controller through the isGranted method, here are two examples and the documentation that explains it.
class ExampleClass
{
private Security $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function __invoke()
{
if (!$this->security->isGranted('YourRoleName')) {
throw new AccessDeniedException('Access Denied.');
}
...
}
}
Extend AbstractController
class ExampleClass extends AbstractController
{
public function myMethod()
{
if (!$this->isGranted('YourRoleName')) {
throw new AccessDeniedException('Access Denied.');
}
...
}
}
You can deepen the documentation here
If what you want to do is something generic you should read the information of the request object in the listener, for example:
public function example(ViewEvent $event)
{
$request = $event->getRequest();
$method = $request->getMethod();
$routeName = $request->attributes->get('_route');
}
And in this way develop your logic together with the Security service to obtain the result you want.