1
1
.. index ::
2
2
single: Security; Data Permission Voters
3
3
4
- How to implement your own Voter to check the permission for a object agains a user
5
- ==================================================================================
4
+ How to implement your own Voter to check user permissions for accessing a given object
5
+ ======================================================================================
6
6
7
7
In Symfony2 you can check the permission to access data by the
8
- :doc: `ACL module </cookbook/security/acl >` which is a bit overhelming
9
- for many applications. A much easier solution is working with custom
8
+ :doc: `ACL module </cookbook/security/acl >`, which is a bit overwhelming
9
+ for many applications. A much easier solution is to work with custom voters
10
10
voters, which are like simple conditional statements. Voters can be
11
11
also used to check for permission as a part or even the whole
12
- application: :doc: `cookbook/security/voters `.
12
+ application: :doc: `"/ cookbook/security/voters" `.
13
13
14
14
.. tip ::
15
15
16
16
It is good to understand the basics about what and how
17
17
:doc: `authorization </components/security/authorization >` works.
18
18
19
- How symfony works with voters
20
- -----------------------------
19
+ How Symfony Uses Voters
20
+ -----------------------
21
21
22
- In order to use voters you have to understand how symfony works with them.
23
- In general all registered custom voters will be called every time you ask
24
- symfony about permission (ACL). In general there are three different
22
+ In order to use voters, you have to understand how Symfony works with them.
23
+ In general, all registered custom voters will be called every time you ask
24
+ Symfony about permissions (ACL). In general there are three different
25
25
approaches on how to handle the feedback from all voters:
26
- :ref: `components-security-access-decision-manager `.
26
+ :ref: `" components-security-access-decision-manager" `.
27
27
28
28
The Voter Interface
29
29
-------------------
30
30
31
31
A custom voter must implement
32
32
:class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ VoterInterface `,
33
- which requires the following three methods :
33
+ which has this structure :
34
34
35
35
.. code-block :: php
36
36
@@ -55,53 +55,52 @@ values:
55
55
* ``VoterInterface::ACCESS_ABSTAIN ``: The voter cannot decide if the user is granted or not
56
56
* ``VoterInterface::ACCESS_DENIED ``: The user is not allowed to access the application
57
57
58
- In this example, you'll check if the user will have access to a specific object according to your custom conditions (e.g. he must be the owner of the object). If the condition fails, you'll return
58
+ In this example, you'll check if the user will have access to a specific
59
+ object according to your custom conditions (e.g. he must be the owner of
60
+ the object). If the condition fails, you'll return
59
61
``VoterInterface::ACCESS_DENIED ``, otherwise you'll return
60
- ``VoterInterface::ACCESS_GRANTED ``. In case the responsebility for this decision belong not to this voter, he will return
61
- ``VoterInterface::ACCESS_ABSTAIN ``.
62
+ ``VoterInterface::ACCESS_GRANTED ``. In case the responsibility for this decision
63
+ belongs not to this voter, it will return ``VoterInterface::ACCESS_ABSTAIN ``.
62
64
63
65
Creating the Custom Voter
64
66
-------------------------
65
67
66
- You could store your Voter for the view and edit method of a post within ACME/DemoBundle/Security/Authorization/Document/PostVoter.php .
68
+ You could store your Voter to check permission for the view and edit action like following .
67
69
68
70
.. code-block :: php
69
71
70
- // src/Acme/DemoBundle/Security/Authorization/Document /PostVoter.php
71
- namespace Acme\DemoBundle\Security\Authorization\Document ;
72
+ // src/Acme/DemoBundle/Security/Authorization/Entity /PostVoter.php
73
+ namespace Acme\DemoBundle\Security\Authorization\Entity ;
72
74
73
75
use Symfony\Component\DependencyInjection\ContainerInterface;
74
76
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
75
77
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
78
+ use Symfony\Component\Security\Core\User\UserInterface;
76
79
77
80
class PostVoter implements VoterInterface
78
81
{
79
- private $container;
80
-
81
- public function __construct(ContainerInterface $container)
82
- {
83
- $this->container = $container;
84
- }
85
82
86
83
public function supportsAttribute($attribute)
87
84
{
88
- return in_array($attribute, array(
89
- 'view',
90
- 'edit'
91
- ));
85
+ return in_array($attribute, array(
86
+ 'view',
87
+ 'edit',
88
+ ));
92
89
}
93
90
94
91
public function supportsClass($class)
95
92
{
96
- // could be "ACME \DemoBundle\Entity\Post" as well
97
- $array = array("ACME \DemoBundle\Document \Post");
93
+ // could be "Acme \DemoBundle\Entity\Post" as well
94
+ $array = array("Acme \DemoBundle\Entity \Post");
98
95
99
96
foreach ($array as $item) {
100
97
// check with stripos in case doctrine is using a proxy class for this object
101
- if (stripos($s, $item) !== FALSE) {
98
+ if (stripos($s, $item) !== false) {
99
+
102
100
return true;
103
101
}
104
102
}
103
+
105
104
return false;
106
105
}
107
106
@@ -111,32 +110,36 @@ You could store your Voter for the view and edit method of a post within ACME/De
111
110
$user = $token->getUser();
112
111
113
112
// check if class of this object is supported by this voter
114
- if ( !($this->supportsClass(get_class($object))) ) {
113
+ if (!($this->supportsClass(get_class($object)))) {
114
+
115
115
return VoterInterface::ACCESS_ABSTAIN;
116
116
}
117
117
118
118
// check if the given attribute is covered by this voter
119
119
foreach ($attributes as $attribute) {
120
- if ( !$this->supportsAttribute($attribute) ) {
120
+ if (!$this->supportsAttribute($attribute)) {
121
+
121
122
return VoterInterface::ACCESS_ABSTAIN;
122
123
}
123
124
}
124
125
125
126
// check if given user is instance of user interface
126
- if ( !($user instanceof UserInterface) ) {
127
+ if (!($user instanceof UserInterface)) {
128
+
127
129
return VoterInterface::ACCESS_DENIED;
128
130
}
129
131
130
132
switch($this->attributes[0]) {
131
-
132
133
case 'view':
133
- if($object->isPrivate() === false) {
134
+ if ($object->isPrivate() === false) {
135
+
134
136
return VoterInterface::ACCESS_GRANTED;
135
137
}
136
138
break;
137
139
138
140
case 'edit':
139
- if($object->getOwner()->getId() === $user->getId()) {
141
+ if ($user->getId() === $object->getOwner()->getId()) {
142
+
140
143
return VoterInterface::ACCESS_GRANTED;
141
144
}
142
145
break;
@@ -164,10 +167,9 @@ and tag it as a "security.voter":
164
167
165
168
# src/Acme/AcmeBundle/Resources/config/services.yml
166
169
services :
167
- security.access.post_document_voter :
168
- class : Acme\DemoBundle\Security\Authorization\Document \PostVoter
170
+ security.access.post_voter :
171
+ class : Acme\DemoBundle\Security\Authorization\Entity \PostVoter
169
172
public : false
170
- arguments : [@service_container]
171
- # we need to assign this service to be a security voter
173
+ # the service gets tagged as a voter
172
174
tags :
173
175
- { name: security.voter }
0 commit comments