Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit967ecfb

Browse files
committed
Merge branch '6.4' into 7.2
* 6.4: [Security] Update the main voters article
2 parents5cd2d73 +7ed9a6f commit967ecfb

File tree

1 file changed

+83
-40
lines changed

1 file changed

+83
-40
lines changed

‎security/voters.rst

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,6 @@ which makes creating a voter even easier::
5050

5151
.. _how-to-use-the-voter-in-a-controller:
5252

53-
..tip::
54-
55-
Checking each voter several times can be time consuming for applications
56-
that perform a lot of permission checks. To improve performance in those cases,
57-
you can make your voters implement the:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface`.
58-
This allows the access decision manager to remember the attribute and type
59-
of subject supported by the voter, to only call the needed voters each time.
60-
6153
Setup: Checking for Access in a Controller
6254
------------------------------------------
6355

@@ -292,6 +284,89 @@ If you're using the :ref:`default services.yaml configuration <service-container
292284
you're done! Symfony will automatically pass the ``security.helper``
293285
service when instantiating your voter (thanks to autowiring).
294286

287+
Improving Voter Performance
288+
---------------------------
289+
290+
If your application defines many voters and checks permissions on many objects
291+
during a single request, this can impact performance. Most of the time, voters
292+
only care about specific permissions (attributes), such as ``EDIT_BLOG_POST``,
293+
or specific object types, such as ``User`` or ``Invoice``. That's why Symfony
294+
can cache the voter resolution (i.e. the decision to apply or skip a voter for
295+
a given attribute or object).
296+
297+
To enable this optimization, make your voter implement
298+
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface`.
299+
This is already the case when extending the abstract ``Voter`` class shown above.
300+
Then, override one or both of the following methods::
301+
302+
use App\Entity\Post;
303+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
304+
// ...
305+
306+
class PostVoter extends Voter
307+
{
308+
const VIEW = 'view';
309+
const EDIT = 'edit';
310+
311+
protected function supports(string $attribute, mixed $subject): bool
312+
{
313+
// ...
314+
}
315+
316+
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
317+
{
318+
// ...
319+
}
320+
321+
// this method returns true if the voter applies to the given attribute;
322+
// if it returns false, Symfony won't call it again for this attribute
323+
public function supportsAttribute(string $attribute): bool
324+
{
325+
return in_array($attribute, [self::VIEW, self::EDIT], true);
326+
}
327+
328+
// this method returns true if the voter applies to the given object class/type;
329+
// if it returns false, Symfony won't call it again for that type of object
330+
public function supportsAttribute(string $attribute): bool
331+
{
332+
// you can't use a simple Post::class === $subjectType comparison
333+
// because the subject type might be a Doctrine proxy class
334+
return is_a($subjectType, Post::class, true);
335+
}
336+
}
337+
338+
.. _security-voters-change-message-and-status-code:
339+
340+
Changing the message and status code returned
341+
---------------------------------------------
342+
343+
By default, the ``#[IsGranted]`` attribute will throw a
344+
:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
345+
and return an http **403** status code with **Access Denied** as message.
346+
347+
However, you can change this behavior by specifying the message and status code returned::
348+
349+
// src/Controller/PostController.php
350+
351+
// ...
352+
use Symfony\Component\Security\Http\Attribute\IsGranted;
353+
354+
class PostController extends AbstractController
355+
{
356+
#[Route('/posts/{id}', name: 'post_show')]
357+
#[IsGranted('show', 'post', 'Post not found', 404)]
358+
public function show(Post $post): Response
359+
{
360+
// ...
361+
}
362+
}
363+
364+
..tip::
365+
366+
If the status code is different than 403, an
367+
:class:`Symfony\\Component\\HttpKernel\\Exception\\HttpException`
368+
will be thrown instead.
369+
295370
.. _security-voters-change-strategy:
296371

297372
Changing the Access Decision Strategy
@@ -463,35 +538,3 @@ must implement the :class:`Symfony\\Component\\Security\\Core\\Authorization\\Ac
463538
// ...
464539
;
465540
};
466-
467-
.. _security-voters-change-message-and-status-code:
468-
469-
Changing the message and status code returned
470-
---------------------------------------------
471-
472-
By default, the ``#[IsGranted]`` attribute will throw a
473-
:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
474-
and return an http **403** status code with **Access Denied** as message.
475-
476-
However, you can change this behavior by specifying the message and status code returned::
477-
478-
// src/Controller/PostController.php
479-
480-
// ...
481-
use Symfony\Component\Security\Http\Attribute\IsGranted;
482-
483-
class PostController extends AbstractController
484-
{
485-
#[Route('/posts/{id}', name: 'post_show')]
486-
#[IsGranted('show', 'post', 'Post not found', 404)]
487-
public function show(Post $post): Response
488-
{
489-
// ...
490-
}
491-
}
492-
493-
..tip::
494-
495-
If the status code is different than 403, an
496-
:class:`Symfony\\Component\\HttpKernel\\Exception\\HttpException`
497-
will be thrown instead.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp