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

Commit968cb65

Browse files
inoryyweaverryan
authored andcommitted
add & update doc entries on AbstractVoter implementation
1 parentae27dd1 commit968cb65

File tree

3 files changed

+101
-78
lines changed

3 files changed

+101
-78
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.. code-block:: php
2+
3+
abstract class AbstractVoter implements VoterInterface
4+
{
5+
public function supportsAttribute($attribute);
6+
public function supportsClass($class);
7+
public function vote(TokenInterface $token, $object, array $attributes);
8+
9+
abstract protected function getSupportedClasses();
10+
abstract protected function getSupportedAttributes();
11+
abstract protected function isGranted($attribute, $object, $user = null);
12+
}
13+
14+
Behind the scenes this class implements the
15+
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`,
16+
which has this structure:
17+
18+
.. include:: /cookbook/security/voter_interface.rst.inc
19+
20+
The basic functionality covering common use cases is provided
21+
and end developer is expected to implement the abstract methods.
22+
23+
The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses`
24+
method is used to provide an array of supported classes, i.e. ['\Acme\DemoBundle\Model\Product']
25+
26+
The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedAttributes`
27+
method is used to provide an array of supported attributes, i.e. ['CREATE', 'READ']
28+
29+
The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted`
30+
method must implement the business logic that verifies whether or not a given
31+
user is allowed a given attribute on a given object. This method must return a boolean.

‎cookbook/security/voters.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ the security layer. This can be done easily through the service container.
9292
methods in your implementation of the ``vote()`` method and return ``ACCESS_ABSTAIN``
9393
if your voter does not support the class or attribute.
9494

95+
96+
..tip::
97+
98+
An
99+
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter`
100+
is provided to cover the common use cases when implementing security voters.
101+
95102
Declaring the Voter as a Service
96103
--------------------------------
97104

‎cookbook/security/voters_data_permission.rst

Lines changed: 63 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ How Symfony Uses Voters
2525

2626
In order to use voters, you have to understand how Symfony works with them.
2727
All voters are called each time you use the ``isGranted()`` method on Symfony's
28-
authorization checker (i.e. the ``security.authorization_checker`` service). Each
28+
authorization checker (i.e. the ``security.authorization_checker`` service). Each
2929
one decides if the current user should have access to some resource.
3030

3131
Ultimately, Symfony uses one of three different approaches on what to do
@@ -37,11 +37,19 @@ For more information take a look at
3737
The Voter Interface
3838
-------------------
3939

40-
A custom voter must implement
41-
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`,
42-
which has this structure:
40+
A custom voter needs to implement
41+
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`
42+
or extend:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter`,
43+
which makes creating a voter even easier.
4344

44-
..include::/cookbook/security/voter_interface.rst.inc
45+
..code-block::php
46+
47+
abstract class AbstractVoter implements VoterInterface
48+
{
49+
abstract protected function getSupportedClasses();
50+
abstract protected function getSupportedAttributes();
51+
abstract protected function isGranted($attribute, $object, $user = null);
52+
}
4553
4654
In this example, the voter will check if the user has access to a specific
4755
object according to your custom conditions (e.g. they must be the owner of
@@ -61,90 +69,74 @@ edit a particular object. Here's an example implementation:
6169
// src/AppBundle/Security/Authorization/Voter/PostVoter.php
6270
namespace AppBundle\Security\Authorization\Voter;
6371
64-
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
65-
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
72+
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
6673
use Symfony\Component\Security\Core\User\UserInterface;
6774
68-
class PostVoterimplements VoterInterface
75+
class PostVoterextends AbstractVoter
6976
{
7077
const VIEW = 'view';
7178
const EDIT = 'edit';
7279
73-
public functionsupportsAttribute($attribute)
80+
protected functiongetSupportedAttributes()
7481
{
75-
return in_array($attribute, array(
76-
self::VIEW,
77-
self::EDIT,
78-
));
82+
return array(self::VIEW, self::EDIT);
7983
}
8084
81-
public functionsupportsClass($class)
85+
protected functiongetSupportedClasses()
8286
{
83-
$supportedClass = 'AppBundle\Entity\Post';
84-
85-
return $supportedClass === $class || is_subclass_of($class, $supportedClass);
87+
return array('AppBundle\Entity\Post');
8688
}
8789
88-
/**
89-
* @var \AppBundle\Entity\Post $post
90-
*/
91-
public function vote(TokenInterface $token, $post, array $attributes)
90+
protected function isGranted($attribute, $post, $user = null)
9291
{
93-
// check if class of this object is supported by this voter
94-
if (!$this->supportsClass(get_class($post))) {
95-
return VoterInterface::ACCESS_ABSTAIN;
96-
}
97-
98-
// check if the voter is used correct, only allow one attribute
99-
// this isn't a requirement, it's just one easy way for you to
100-
// design your voter
101-
if (1 !== count($attributes)) {
102-
throw new \InvalidArgumentException(
103-
'Only one attribute is allowed for VIEW or EDIT'
104-
);
105-
}
106-
107-
// set the attribute to check against
108-
$attribute = $attributes[0];
109-
110-
// check if the given attribute is covered by this voter
111-
if (!$this->supportsAttribute($attribute)) {
112-
return VoterInterface::ACCESS_ABSTAIN;
113-
}
114-
115-
// get current logged in user
116-
$user = $token->getUser();
117-
11892
// make sure there is a user object (i.e. that the user is logged in)
11993
if (!$user instanceof UserInterface) {
120-
return VoterInterface::ACCESS_DENIED;
94+
return false;
95+
}
96+
97+
// the data object could have for example a method isPrivate()
98+
// which checks the Boolean attribute $private
99+
if ($attribute == self::VIEW && !$post->isPrivate()) {
100+
return true;
121101
}
122102
123-
switch($attribute) {
124-
case self::VIEW:
125-
// the data object could have for example a method isPrivate()
126-
// which checks the boolean attribute $private
127-
if (!$post->isPrivate()) {
128-
return VoterInterface::ACCESS_GRANTED;
129-
}
130-
break;
131-
132-
case self::EDIT:
133-
// we assume that our data object has a method getOwner() to
134-
// get the current owner user entity for this data object
135-
if ($user->getId() === $post->getOwner()->getId()) {
136-
return VoterInterface::ACCESS_GRANTED;
137-
}
138-
break;
103+
// we assume that our data object has a method getOwner() to
104+
// get the current owner user entity for this data object
105+
if ($attribute == self::EDIT && $user->getId() === $post->getOwner()->getId()) {
106+
return true;
139107
}
140108
141-
returnVoterInterface::ACCESS_DENIED;
109+
returnfalse;
142110
}
143111
}
144112
145113
That's it! The voter is done. The next step is to inject the voter into
146114
the security layer.
147115

116+
To recap, here's what's expected from the three abstract methods:
117+
118+
:method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses`
119+
It tells Symfony that your voter should be called whenever an object of one
120+
of the given classes is passed to ``isGranted()`` For example, if you return
121+
``array('AppBundle\Model\Product')``, Symfony will call your voter when a
122+
``Product`` object is passed to ``isGranted()``.
123+
124+
:method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedAttributes`
125+
It tells Symfony that your voter should be called whenever one of these
126+
strings is passes as the first argument to ``isGranted()``. For example, if
127+
you return ``array('CREATE', 'READ')``, then Symfony will call your voter
128+
when one of these is passed to ``isGranted()``.
129+
130+
:method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted`
131+
It implements the business logic that verifies whether or not a given user is
132+
allowed access to a given attribute (e.g. ``CREATE`` or ``READ``) on a given
133+
object. This method must return a boolean.
134+
135+
..note::
136+
137+
Currently, to use the ``AbstractVoter`` base class, you must be creating a
138+
voter where an object is always passed to ``isGranted()``.
139+
148140
Declaring the Voter as a Service
149141
--------------------------------
150142

@@ -203,6 +195,7 @@ from the authorization checker is called.
203195
204196
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
205197
use Symfony\Component\HttpFoundation\Response;
198+
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
206199
207200
class PostController extends Controller
208201
{
@@ -212,25 +205,17 @@ from the authorization checker is called.
212205
$post = ...;
213206
214207
// keep in mind, this will call all registered security voters
215-
$this->denyAccessUnlessGranted('view', $post, 'Unauthorized access!');
216-
217-
// the equivalent code without using the denyAccessUnlessGranted() shortcut
218-
// use Symfony\Component\Security\Core\Exception\AccessDeniedException;
219-
//
220-
// if (false === $this->get('security.authorization_checker')->isGranted('view', $post)) {
221-
// throw new AccessDeniedException('Unauthorized access!');
222-
// }
208+
if (false === $this->get('security.authorization_checker')->isGranted('view', $post)) {
209+
throw new AccessDeniedException('Unauthorised access!');
210+
}
223211
224212
return new Response('<h1>'.$post->getName().'</h1>');
225213
}
226214
}
227215
228216
..versionadded::2.6
229-
The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior
230-
to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service.
231-
232-
..versionadded::2.6
233-
The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6 as a shortcut.
234-
It uses ``security.authorization_checker`` and throws an ``AccessDeniedException`` if needed.
217+
The ``security.authorization_checker`` service was introduced in Symfony 2.6.
218+
Prior to Symfony 2.6, you had to use the ``isGranted()`` method of the
219+
``security.context`` service.
235220

236221
It's that easy!

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp