@@ -22,10 +22,10 @@ for each ``access_control`` entry, which determines whether or not a given
22
22
access control should be used on this request. The following ``access_control ``
23
23
options are used for matching:
24
24
25
- * ``path ``
26
- * ``ip `` or ``ips `` ( netmasks are also supported)
27
- * ``host ``
28
- * ``methods ``
25
+ * ``path ``: a regular expression (without delimiters)
26
+ * ``ip `` or ``ips ``: netmasks are also supported
27
+ * ``host ``: a regular expression
28
+ * ``methods ``: one or many methods
29
29
30
30
Take the following ``access_control `` entries as an example:
31
31
@@ -37,10 +37,11 @@ Take the following ``access_control`` entries as an example:
37
37
security :
38
38
# ...
39
39
access_control :
40
- - { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
41
- - { path: ^/admin, roles: ROLE_USER_HOST, host: symfony\.com$ }
42
- - { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
43
- - { path: ^/admin, roles: ROLE_USER }
40
+ - { path: '^/admin', roles: ROLE_USER_IP, ip: 127.0.0.1 }
41
+ - { path: '^/admin', roles: ROLE_USER_HOST, host: symfony\.com$ }
42
+ - { path: '^/admin', roles: ROLE_USER_METHOD, methods: [POST, PUT] }
43
+ # when defining multiple roles, users must have at least one of them (it's like an OR condition)
44
+ - { path: '^/admin', roles: [ROLE_MANAGER, ROLE_ADMIN] }
44
45
45
46
.. code-block :: xml
46
47
@@ -57,7 +58,8 @@ Take the following ``access_control`` entries as an example:
57
58
<rule path =" ^/admin" role =" ROLE_USER_IP" ip =" 127.0.0.1" />
58
59
<rule path =" ^/admin" role =" ROLE_USER_HOST" host =" symfony\.com$" />
59
60
<rule path =" ^/admin" role =" ROLE_USER_METHOD" methods =" POST, PUT" />
60
- <rule path =" ^/admin" role =" ROLE_USER" />
61
+ <!-- when defining multiple roles, users must have at least one of them (it's like an OR condition) -->
62
+ <rule path =" ^/admin" roles =" ROLE_ADMIN, ROLE_MANAGER" />
61
63
</config >
62
64
</srv : container >
63
65
@@ -69,31 +71,32 @@ Take the following ``access_control`` entries as an example:
69
71
'access_control' => [
70
72
[
71
73
'path' => '^/admin',
72
- 'role ' => 'ROLE_USER_IP',
73
- 'ip ' => '127.0.0.1',
74
+ 'roles ' => 'ROLE_USER_IP',
75
+ 'ips ' => '127.0.0.1',
74
76
],
75
77
[
76
78
'path' => '^/admin',
77
- 'role ' => 'ROLE_USER_HOST',
79
+ 'roles ' => 'ROLE_USER_HOST',
78
80
'host' => 'symfony\.com$',
79
81
],
80
82
[
81
83
'path' => '^/admin',
82
- 'role ' => 'ROLE_USER_METHOD',
84
+ 'roles ' => 'ROLE_USER_METHOD',
83
85
'methods' => 'POST, PUT',
84
86
],
85
87
[
86
88
'path' => '^/admin',
87
- 'role' => 'ROLE_USER',
89
+ // when defining multiple roles, users must have at least one of them (it's like an OR condition)
90
+ 'roles' => ['ROLE_MANAGER', 'ROLE_ADMIN'],
88
91
],
89
92
],
90
93
]);
91
94
92
95
For each incoming request, Symfony will decide which ``access_control ``
93
96
to use based on the URI, the client's IP address, the incoming host name,
94
97
and the request method. Remember, the first rule that matches is used, and
95
- if ``ip ``, ``host `` or ``method `` are not specified for an entry, that `` access_control ``
96
- will match any ``ip ``, ``host `` or ``method ``:
98
+ if ``ips ``, ``host `` or ``methods `` are not specified for an entry, that
99
+ `` access_control `` will match any ``ips ``, ``host `` or ``methods ``:
97
100
98
101
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
99
102
| URI | IP | HOST | METHOD | ``access_control `` | Why? |
@@ -114,9 +117,10 @@ will match any ``ip``, ``host`` or ``method``:
114
117
| ``/admin/user `` | 168.0.0.1 | example.com | POST | rule #3 (``ROLE_USER_METHOD ``) | The ``ip `` and ``host `` don't match the first two entries, |
115
118
| | | | | | but the third - ``ROLE_USER_METHOD `` - matches and is used. |
116
119
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
117
- | ``/admin/user `` | 168.0.0.1 | example.com | GET | rule #4 (``ROLE_USER ``) | The ``ip ``, ``host `` and ``method `` prevent the first |
120
+ | ``/admin/user `` | 168.0.0.1 | example.com | GET | rule #4 (``ROLE_MANAGER ``) | The ``ip ``, ``host `` and ``method `` prevent the first |
118
121
| | | | | | three entries from matching. But since the URI matches the |
119
- | | | | | | ``path `` pattern of the ``ROLE_USER `` entry, it is used. |
122
+ | | | | | | ``path `` pattern, then the ``ROLE_MANAGER `` (or the |
123
+ | | | | | | ``ROLE_ADMIN ``) is used. |
120
124
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
121
125
| ``/foo `` | 127.0.0.1 | symfony.com | POST | matches no entries | This doesn't match any ``access_control `` rules, since its |
122
126
| | | | | | URI doesn't match any of the ``path `` values. |
@@ -142,6 +146,14 @@ options:
142
146
does not match this value (e.g. ``https ``), the user will be redirected
143
147
(e.g. redirected from ``http `` to ``https ``, or vice versa).
144
148
149
+ .. tip ::
150
+
151
+ Behind the scenes, the array value of ``roles `` is passed as the
152
+ ``$attributes `` argument to each voter in the application with the
153
+ :class: `Symfony\\ Component\\ HttpFoundation\\ Request ` as ``$subject ``. You
154
+ can learn how to use your custom attributes by reading
155
+ :ref: `security/custom-voter `.
156
+
145
157
.. tip ::
146
158
147
159
If access is denied, the system will try to authenticate the user if not
@@ -178,8 +190,8 @@ pattern so that it is only accessible by requests from the local server itself:
178
190
access_control :
179
191
#
180
192
# the 'ips' option supports IP addresses and subnet masks
181
- - { path: ^/internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
182
- - { path: ^/internal, roles: ROLE_NO_ACCESS }
193
+ - { path: ' ^/internal' , roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
194
+ - { path: ' ^/internal' , roles: ROLE_NO_ACCESS }
183
195
184
196
.. code-block :: xml
185
197
@@ -212,13 +224,13 @@ pattern so that it is only accessible by requests from the local server itself:
212
224
'access_control' => [
213
225
[
214
226
'path' => '^/internal',
215
- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
227
+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
216
228
// the 'ips' option supports IP addresses and subnet masks
217
229
'ips' => ['127.0.0.1', '::1'],
218
230
],
219
231
[
220
232
'path' => '^/internal',
221
- 'role ' => 'ROLE_NO_ACCESS',
233
+ 'roles ' => 'ROLE_NO_ACCESS',
222
234
],
223
235
],
224
236
]);
@@ -263,7 +275,10 @@ key:
263
275
access_control :
264
276
-
265
277
path : ^/_internal/secure
266
- allow_if : " '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')"
278
+ # the 'role' and 'allow-if' options work like an OR expression, so
279
+ # access is granted if the expression is TRUE or the user has ROLE_ADMIN
280
+ roles : ' ROLE_ADMIN'
281
+ allow_if : " '127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')"
267
282
268
283
.. code-block :: xml
269
284
@@ -276,8 +291,11 @@ key:
276
291
https://symfony.com/schema/dic/services/services-1.0.xsd" >
277
292
278
293
<config >
294
+ <!-- the 'role' and 'allow-if' options work like an OR expression, so
295
+ access is granted if the expression is TRUE or the user has ROLE_ADMIN -->
279
296
<rule path =" ^/_internal/secure"
280
- allow-if =" '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" />
297
+ role =" ROLE_ADMIN"
298
+ allow-if =" '127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')" />
281
299
</config >
282
300
</srv : container >
283
301
@@ -286,13 +304,22 @@ key:
286
304
'access_control' => [
287
305
[
288
306
'path' => '^/_internal/secure',
289
- 'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")',
307
+ // the 'role' and 'allow-if' options work like an OR expression, so
308
+ // access is granted if the expression is TRUE or the user has ROLE_ADMIN
309
+ 'roles' => 'ROLE_ADMIN',
310
+ 'allow_if' => '"127.0.0.1" == request.getClientIp() or request.header.has('X-Secure-Access')',
290
311
],
291
312
],
292
313
293
- In this case, when the user tries to access any URL starting with ``/_internal/secure ``,
294
- they will only be granted access if the IP address is ``127.0.0.1 `` or if
295
- the user has the ``ROLE_ADMIN `` role.
314
+ In this case, when the user tries to access any URL starting with
315
+ ``/_internal/secure ``, they will only be granted access if the IP address is
316
+ ``127.0.0.1 `` or a secure header, or if the user has the ``ROLE_ADMIN `` role.
317
+
318
+ .. note ::
319
+
320
+ Internally ``allow_if `` triggers the built-in
321
+ :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ ExpressionVoter `
322
+ as like it was part of the attributes defined in the ``roles `` option.
296
323
297
324
Inside the expression, you have access to a number of different variables
298
325
and functions including ``request ``, which is the Symfony
@@ -343,7 +370,7 @@ the user will be redirected to ``https``:
343
370
'access_control' => [
344
371
[
345
372
'path' => '^/cart/checkout',
346
- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
373
+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
347
374
'requires_channel' => 'https',
348
375
],
349
376
],
0 commit comments