@@ -256,6 +256,107 @@ and tag it with ``security.voter``:
256
256
You're done! Now, when you :ref: `call isGranted() with view/edit and a Post object <how-to-use-the-voter-in-a-controller >`,
257
257
your voter will be executed and you can control access.
258
258
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
+
259
360
.. _security-voters-change-strategy :
260
361
261
362
Changing the Access Decision Strategy
0 commit comments