Skip to content

Commit a4c7d6e

Browse files
committed
adding a section about calling isGranted() from within a voter
1 parent 20cead6 commit a4c7d6e

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

cookbook/security/voters.rst

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,107 @@ and tag it with ``security.voter``:
256256
You're done! Now, when you :ref:`call isGranted() with view/edit and a Post object <how-to-use-the-voter-in-a-controller>`,
257257
your voter will be executed and you can control access.
258258

259+
Checking for Roles inside a Voter
260+
---------------------------------
261+
262+
.. versionadded:: 2.8
263+
The ability to inject the ``AccessDecisionManager`` is new in 2.8: it caused
264+
a CircularReferenceException before. In earlier versions, you must inject the
265+
``service_container`` itself and fetch out the ``security.authorization_checker``
266+
to use ``isGranted()``.
267+
268+
What if you want to call ``isGranted()`` fomr *inside* your voter - e.g. you want
269+
to see if the current user has ``ROLE_SUPER_ADMIN``. That's possible by injecting
270+
the ``AccessDecisionManager`` into your voter. You can use this to, for example,
271+
*always* allow access to a user with ``ROLE_SUPER_ADMIN``::
272+
273+
// src/AppBundle/Security/PostVoter.php
274+
// ...
275+
276+
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
277+
278+
class PostVoter extends Voter
279+
{
280+
// ...
281+
282+
private $decisionManager;
283+
284+
public function __construct(AccessDecisionManagerInterface $decisionManager)
285+
{
286+
$this->decisionManager = $decisionManager;
287+
}
288+
289+
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
290+
{
291+
// ...
292+
293+
// ROLE_SUPER_ADMIN can do anything! The power!
294+
if ($this->decisionManager->decide($token, array('ROLE_SUPER_ADMIN'))) {
295+
return true;
296+
}
297+
298+
// ... all the normal voter logic
299+
}
300+
}
301+
302+
Next, update ``services.yml`` to inject the ``security.access.decision_manager``
303+
service:
304+
305+
.. configuration-block::
306+
307+
.. code-block:: yaml
308+
309+
# app/config/services.yml
310+
services:
311+
app.post_voter:
312+
class: AppBundle\Security\PostVoter
313+
arguments: ['@security.access.decision_manager']
314+
tags:
315+
- { name: security.voter }
316+
317+
.. code-block:: xml
318+
319+
<!-- app/config/services.xml -->
320+
<?xml version="1.0" encoding="UTF-8" ?>
321+
<container xmlns="http://symfony.com/schema/dic/services"
322+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
323+
xsi:schemaLocation="http://symfony.com/schema/dic/services
324+
http://symfony.com/schema/dic/services/services-1.0.xsd">
325+
326+
<services>
327+
<service id="app.post_voter"
328+
class="AppBundle\Security\Authorization\Voter\PostVoter"
329+
public="false"
330+
>
331+
<argument type="service" id="security.access.decision_manager"/>
332+
333+
<tag name="security.voter" />
334+
</service>
335+
</services>
336+
</container>
337+
338+
.. code-block:: php
339+
340+
// app/config/services.php
341+
use Symfony\Component\DependencyInjection\Definition;
342+
use Symfony\Component\DependencyInjection\Reference;
343+
344+
$container->register('app.post_voter', 'AppBundle\Security\Authorization\Voter\PostVoter')
345+
->addArgument(new Reference('security.access.decision_manager'))
346+
->setPublic(false)
347+
->addTag('security.voter')
348+
;
349+
350+
That's it! Calling ``decide()`` on the ``AccessDecisionManager`` is essentially
351+
the same as calling ``isGranted()`` on the normal ``security.authorization_checker``
352+
service (it's just a little lower-level, which is necessary for a voter).
353+
354+
.. note::
355+
356+
The ``security.access.decision_manager`` is private. This means you can't access
357+
it directly from a controller: you can only inject it into other services. That's
358+
ok: use ``security.authorization_checker`` instead in all cases except for voters.
359+
259360
.. _security-voters-change-strategy:
260361

261362
Changing the Access Decision Strategy

0 commit comments

Comments
 (0)