@@ -24,11 +24,11 @@ for each ``access_control`` entry, which determines whether or not a given
2424access control should be used on this request. The following ``access_control ``
2525options are used for matching:
2626
27- * ``path ``
28- * ``ip `` or ``ips `` ( netmasks are also supported)
29- * ``port ``
30- * ``host ``
31- * ``methods ``
27+ * ``path ``: a regular expression (without delimiters)
28+ * ``ip `` or ``ips ``: netmasks are also supported
29+ * ``port ``: an integer
30+ * ``host ``: a regular expression
31+ * ``methods ``: one or many methods
3232
3333Take the following ``access_control `` entries as an example:
3434
@@ -40,11 +40,12 @@ Take the following ``access_control`` entries as an example:
4040 security :
4141 # ...
4242 access_control :
43- - { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
44- - { path: ^/admin, roles: ROLE_USER_PORT, ip: 127.0.0.1, port: 8080 }
45- - { path: ^/admin, roles: ROLE_USER_HOST, host: symfony\.com$ }
46- - { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
47- - { path: ^/admin, roles: ROLE_USER }
43+ - { path: '^/admin', roles: ROLE_USER_IP, ip: 127.0.0.1 }
44+ - { path: '^/admin', roles: ROLE_USER_PORT, ip: 127.0.0.1, port: 8080 }
45+ - { path: '^/admin', roles: ROLE_USER_HOST, host: symfony\.com$ }
46+ - { path: '^/admin', roles: ROLE_USER_METHOD, methods: [POST, PUT] }
47+ # when defining multiple roles, users must have at least one of them (it's like an OR condition)
48+ - { path: '^/admin', roles: [ROLE_MANAGER, ROLE_ADMIN] }
4849
4950 .. code-block :: xml
5051
@@ -62,7 +63,8 @@ Take the following ``access_control`` entries as an example:
6263 <rule path =" ^/admin" role =" ROLE_USER_PORT" ip =" 127.0.0.1" port =" 8080" />
6364 <rule path =" ^/admin" role =" ROLE_USER_HOST" host =" symfony\.com$" />
6465 <rule path =" ^/admin" role =" ROLE_USER_METHOD" methods =" POST, PUT" />
65- <rule path =" ^/admin" role =" ROLE_USER" />
66+ <!-- when defining multiple roles, users must have at least one of them (it's like an OR condition) -->
67+ <rule path =" ^/admin" roles =" ROLE_ADMIN, ROLE_MANAGER" />
6668 </config >
6769 </srv : container >
6870
@@ -74,28 +76,29 @@ Take the following ``access_control`` entries as an example:
7476 'access_control' => [
7577 [
7678 'path' => '^/admin',
77- 'role ' => 'ROLE_USER_IP',
78- 'ip ' => '127.0.0.1',
79+ 'roles ' => 'ROLE_USER_IP',
80+ 'ips ' => '127.0.0.1',
7981 ],
8082 [
8183 'path' => '^/admin',
82- 'role ' => 'ROLE_USER_PORT',
84+ 'roles ' => 'ROLE_USER_PORT',
8385 'ip' => '127.0.0.1',
8486 'port' => '8080',
8587 ],
8688 [
8789 'path' => '^/admin',
88- 'role ' => 'ROLE_USER_HOST',
90+ 'rolse ' => 'ROLE_USER_HOST',
8991 'host' => 'symfony\.com$',
9092 ],
9193 [
9294 'path' => '^/admin',
93- 'role ' => 'ROLE_USER_METHOD',
95+ 'roles ' => 'ROLE_USER_METHOD',
9496 'methods' => 'POST, PUT',
9597 ],
9698 [
9799 'path' => '^/admin',
98- 'role' => 'ROLE_USER',
100+ // when defining multiple roles, users must have at least one of them (it's like an OR condition)
101+ 'roles' => ['ROLE_MANAGER', 'ROLE_ADMIN'],
99102 ],
100103 ],
101104 ]);
@@ -127,9 +130,10 @@ if ``ip``, ``port``, ``host`` or ``method`` are not specified for an entry, that
127130| ``/admin/user `` | 168.0.0.1 | 80 | example.com | POST | rule #4 (``ROLE_USER_METHOD ``) | The ``ip `` and ``host `` don't match the first two entries, |
128131| | | | | | | but the third - ``ROLE_USER_METHOD `` - matches and is used. |
129132+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
130- | ``/admin/user `` | 168.0.0.1 | 80 | example.com | GET | rule #5 (``ROLE_USER ``) | The ``ip ``, ``host `` and ``method `` prevent the first |
133+ | ``/admin/user `` | 168.0.0.1 | 80 | example.com | GET | rule #4 (``ROLE_MANAGER ``) | The ``ip ``, ``host `` and ``method `` prevent the first |
131134| | | | | | | three entries from matching. But since the URI matches the |
132- | | | | | | | ``path `` pattern of the ``ROLE_USER `` entry, it is used. |
135+ | | | | | | | ``path `` pattern, then the ``ROLE_MANAGER `` (or the |
136+ | | | | | | | ``ROLE_ADMIN ``) is used. |
133137+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
134138| ``/foo `` | 127.0.0.1 | 80 | symfony.com | POST | matches no entries | This doesn't match any ``access_control `` rules, since its |
135139| | | | | | | URI doesn't match any of the ``path `` values. |
@@ -155,6 +159,14 @@ options:
155159 does not match this value (e.g. ``https ``), the user will be redirected
156160 (e.g. redirected from ``http `` to ``https ``, or vice versa).
157161
162+ .. tip ::
163+
164+ Behind the scenes, the array value of ``roles `` is passed as the
165+ ``$attributes `` argument to each voter in the application with the
166+ :class: `Symfony\\ Component\\ HttpFoundation\\ Request ` as ``$subject ``. You
167+ can learn how to use your custom attributes by reading
168+ :ref: `security/custom-voter `.
169+
158170.. tip ::
159171
160172 If access is denied, the system will try to authenticate the user if not
@@ -191,8 +203,8 @@ pattern so that it is only accessible by requests from the local server itself:
191203 access_control :
192204 #
193205 # the 'ips' option supports IP addresses and subnet masks
194- - { path: ^/internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
195- - { path: ^/internal, roles: ROLE_NO_ACCESS }
206+ - { path: ' ^/internal' , roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1, 192.168.0.1/24] }
207+ - { path: ' ^/internal' , roles: ROLE_NO_ACCESS }
196208
197209 .. code-block :: xml
198210
@@ -225,13 +237,13 @@ pattern so that it is only accessible by requests from the local server itself:
225237 'access_control' => [
226238 [
227239 'path' => '^/internal',
228- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
240+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
229241 // the 'ips' option supports IP addresses and subnet masks
230242 'ips' => ['127.0.0.1', '::1'],
231243 ],
232244 [
233245 'path' => '^/internal',
234- 'role ' => 'ROLE_NO_ACCESS',
246+ 'roles ' => 'ROLE_NO_ACCESS',
235247 ],
236248 ],
237249 ]);
@@ -276,7 +288,10 @@ key:
276288 access_control :
277289 -
278290 path : ^/_internal/secure
279- allow_if : " '127.0.0.1' == request.getClientIp() or is_granted('ROLE_ADMIN')"
291+ # the 'role' and 'allow-if' options work like an OR expression, so
292+ # access is granted if the expression is TRUE or the user has ROLE_ADMIN
293+ roles : ' ROLE_ADMIN'
294+ allow_if : " '127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')"
280295
281296 .. code-block :: xml
282297
@@ -290,8 +305,11 @@ key:
290305
291306 <config >
292307 <!-- ... -->
308+ <!-- the 'role' and 'allow-if' options work like an OR expression, so
309+ access is granted if the expression is TRUE or the user has ROLE_ADMIN -->
293310 <rule path =" ^/_internal/secure"
294- allow-if =" '127.0.0.1' == request.getClientIp() or is_granted('ROLE_ADMIN')" />
311+ role =" ROLE_ADMIN"
312+ allow-if =" '127.0.0.1' == request.getClientIp() or request.header.has('X-Secure-Access')" />
295313 </config >
296314 </srv : container >
297315
@@ -303,14 +321,23 @@ key:
303321 'access_control' => [
304322 [
305323 'path' => '^/_internal/secure',
306- 'allow_if' => '"127.0.0.1" == request.getClientIp() or is_granted("ROLE_ADMIN")',
324+ // the 'role' and 'allow-if' options work like an OR expression, so
325+ // access is granted if the expression is TRUE or the user has ROLE_ADMIN
326+ 'roles' => 'ROLE_ADMIN',
327+ 'allow_if' => '"127.0.0.1" == request.getClientIp() or request.header.has('X-Secure-Access')',
307328 ],
308329 ],
309330 ]);
310331
311- In this case, when the user tries to access any URL starting with ``/_internal/secure ``,
312- they will only be granted access if the IP address is ``127.0.0.1 `` or if
313- the user has the ``ROLE_ADMIN `` role.
332+ In this case, when the user tries to access any URL starting with
333+ ``/_internal/secure ``, they will only be granted access if the IP address is
334+ ``127.0.0.1 `` or a secure header, or if the user has the ``ROLE_ADMIN `` role.
335+
336+ .. note ::
337+
338+ Internally ``allow_if `` triggers the built-in
339+ :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ ExpressionVoter `
340+ as like it was part of the attributes defined in the ``roles `` option.
314341
315342Inside the expression, you have access to a number of different variables
316343and functions including ``request ``, which is the Symfony
@@ -420,7 +447,7 @@ the user will be redirected to ``https``:
420447 'access_control' => [
421448 [
422449 'path' => '^/cart/checkout',
423- 'role ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
450+ 'roles ' => 'IS_AUTHENTICATED_ANONYMOUSLY',
424451 'requires_channel' => 'https',
425452 ],
426453 ],
0 commit comments