@@ -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
+ # Defining many roles means we need one of them (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
+ <!-- Defining many roles, mean we need one of them (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
+ // Defining many roles, mean we need one of them (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. |
@@ -144,6 +148,14 @@ options:
144
148
does not match this value (e.g. ``https ``), the user will be redirected
145
149
(e.g. redirected from ``http `` to ``https ``, or vice versa).
146
150
151
+ .. tip ::
152
+
153
+ Behind the scenes, the array value of ``roles `` is passed as the
154
+ ``$attributes `` argument to each voter in the application with the
155
+ :class: `Symfony\\ Component\\ HttpFoundation\\ Request ` as ``$subject ``. You
156
+ can learn how to use your custom attributes by reading
157
+ :ref: `security/custom-voter `.
158
+
147
159
.. tip ::
148
160
149
161
If access is denied, the system will try to authenticate the user if not
@@ -180,8 +192,8 @@ pattern so that it is only accessible by requests from the local server itself:
180
192
access_control :
181
193
#
182
194
# the 'ips' option supports IP addresses and subnet masks
183
- - { path: ^/internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
184
- - { path: ^/internal, roles: ROLE_NO_ACCESS }
195
+ - { path: ' ^/internal' , roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
196
+ - { path: ' ^/internal' , roles: ROLE_NO_ACCESS }
185
197
186
198
.. code-block :: xml
187
199
@@ -214,13 +226,13 @@ pattern so that it is only accessible by requests from the local server itself:
214
226
'access_control' => [
215
227
[
216
228
'path' => '^/internal',
217
- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
229
+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
218
230
// the 'ips' option supports IP addresses and subnet masks
219
231
'ips' => ['127.0.0.1', '::1'],
220
232
],
221
233
[
222
234
'path' => '^/internal',
223
- 'role ' => 'ROLE_NO_ACCESS',
235
+ 'roles ' => 'ROLE_NO_ACCESS',
224
236
],
225
237
],
226
238
]);
265
277
access_control :
266
278
-
267
279
path : ^/_internal/secure
268
- allow_if : " '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')"
280
+ roles : ' ROLE_ADMIN'
281
+ // with this expression, we need it to be true OR a ROLE_ADMIN
282
+ allow_if : " '127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')"
269
283
270
284
.. code-block :: xml
271
285
279
293
280
294
<config >
281
295
<rule path =" ^/_internal/secure"
282
- allow-if =" '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" />
296
+ role =" ROLE_ADMIN"
297
+ <!-- with this expression, we need it to be true OR a ROLE_ADMIN -->
298
+ allow-if="'127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')" />
283
299
</config >
284
300
</srv : container >
285
301
@@ -288,13 +304,27 @@ key:
288
304
'access_control' => [
289
305
[
290
306
'path' => '^/_internal/secure',
291
- 'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")',
307
+ 'roles' => 'ROLE_ADMIN',
308
+ // with this expression, we need it to be true OR a ROLE_ADMIN
309
+ 'allow_if' => '"127.0.0.1" == request.getClientIp() or request.header.has('X-Secure-Access')',
292
310
],
293
311
],
294
312
295
- In this case, when the user tries to access any URL starting with ``/_internal/secure ``,
296
- they will only be granted access if the IP address is ``127.0.0.1 `` or if
297
- the user has the ``ROLE_ADMIN `` role.
313
+ In this case, when the user tries to access any URL starting with
314
+ ``/_internal/secure ``, they will only be granted access if the IP address is
315
+ ``127.0.0.1 `` or a secure header, or if the user has the ``ROLE_ADMIN `` role.
316
+
317
+ .. note ::
318
+
319
+ Internally ``allow_if `` triggers the built-in
320
+ :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ ExpressionVoter `
321
+ as like it was part of the attributes defined in the ``roles `` option.
322
+ By default, access is granted if one of the attribute is granted. In other
323
+ words, it means ``allow_if `` can grant access even if the
324
+ :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ RoleVoter ` or
325
+ any other voter denied it.
326
+ To change this behavior, you may need to learn more about
327
+ :ref: `access decision strategy <security-voters-change-strategy >`.
298
328
299
329
Inside the expression, you have access to a number of different variables
300
330
and functions including ``request ``, which is the Symfony
@@ -345,7 +375,7 @@ the user will be redirected to ``https``:
345
375
'access_control' => [
346
376
[
347
377
'path' => '^/cart/checkout',
348
- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
378
+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
349
379
'requires_channel' => 'https',
350
380
],
351
381
],
0 commit comments