@@ -864,6 +864,8 @@ options:
864
864
(internally, an :class: `Symfony\\ Component\\ Security\\ Core\\ Exception\\ AccessDeniedException `
865
865
is thrown);
866
866
867
+ * ``allow_if `` If the expression returns false, then access is denied;
868
+
867
869
* ``requires_channel `` If the incoming request's channel (e.g. ``http ``)
868
870
does not match this value (e.g. ``https ``), the user will be redirected
869
871
(e.g. redirected from ``http `` to ``https ``, or vice versa).
@@ -951,6 +953,58 @@ address):
951
953
952
954
* The second access rule is not examined as the first rule matched.
953
955
956
+ .. _book-security-allow-if :
957
+
958
+ Securing by an Expression
959
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
960
+
961
+ .. versionadded :: 2.4
962
+ The ``allow_if `` functionality was introduced in Symfony 2.4.
963
+
964
+ Once an ``access_control `` entry is matched, you can deny access via the
965
+ ``roles `` key or use more complex logic with an expression in the ``allow_if ``
966
+ key:
967
+
968
+ .. configuration-block ::
969
+
970
+ .. code-block :: yaml
971
+
972
+ # app/config/security.yml
973
+ security :
974
+ # ...
975
+ access_control :
976
+ -
977
+ path : ^/_internal/secure
978
+ allow_if : " '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')"
979
+
980
+ .. code-block :: xml
981
+
982
+ <access-control >
983
+ <rule path =" ^/_internal/secure"
984
+ allow-if =" '127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" />
985
+ </access-control >
986
+
987
+ .. code-block :: php
988
+
989
+ 'access_control' => array(
990
+ array(
991
+ 'path' => '^/_internal/secure',
992
+ 'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")',
993
+ ),
994
+ ),
995
+
996
+ In this case, when the user tries to access any URL starting with ``/_internal/secure ``,
997
+ they will only be granted access if the IP address is ``127.0.0.1 `` or if
998
+ the user has the ``ROLE_ADMIN `` role.
999
+
1000
+ Inside the expression, you have access to a number of different variables
1001
+ and functions including ``request ``, which is the Symfony
1002
+ :class: `Symfony\\ Component\\ HttpFoundation\\ Request ` object (see
1003
+ :ref: `component-http-foundation-request `).
1004
+
1005
+ For a list of the other functions and variables, see
1006
+ :ref: `functions and variables <book-security-expression-variables >`.
1007
+
954
1008
.. _book-security-securing-channel :
955
1009
956
1010
Securing by Channel
@@ -1656,6 +1710,8 @@ doesn't need to be defined anywhere - you can just start using it.
1656
1710
Symfony2. If you define your own roles with a dedicated ``Role `` class
1657
1711
(more advanced), don't use the ``ROLE_ `` prefix.
1658
1712
1713
+ .. _book-security-role-hierarchy :
1714
+
1659
1715
Hierarchical Roles
1660
1716
~~~~~~~~~~~~~~~~~~
1661
1717
@@ -1834,6 +1890,33 @@ the built-in helper function:
1834
1890
idea to have a main firewall that covers all URLs (as has been shown
1835
1891
in this chapter).
1836
1892
1893
+ .. _book-security-template-expression :
1894
+
1895
+ .. versionadded :: 2.4
1896
+ The ``expression `` functionality was introduced in Symfony 2.4.
1897
+
1898
+ You can also use expressions inside your templates:
1899
+
1900
+ .. configuration-block ::
1901
+
1902
+ .. code-block :: html+jinja
1903
+
1904
+ {% if is_granted(expression(
1905
+ '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1906
+ )) %}
1907
+ <a href="...">Delete</a>
1908
+ {% endif %}
1909
+
1910
+ .. code-block :: html+php
1911
+
1912
+ <?php if ($view['security']->isGranted(new Expression(
1913
+ '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1914
+ ))): ?>
1915
+ <a href="...">Delete</a>
1916
+ <?php endif; ?>
1917
+
1918
+ For more details on expressions and security, see :ref: `book-security-expressions `.
1919
+
1837
1920
Access Control in Controllers
1838
1921
-----------------------------
1839
1922
@@ -1856,6 +1939,91 @@ method of the security context::
1856
1939
A firewall must be active or an exception will be thrown when the ``isGranted ``
1857
1940
method is called. See the note above about templates for more details.
1858
1941
1942
+ .. _book-security-expressions :
1943
+
1944
+ Complex Access Controls with Expressions
1945
+ ----------------------------------------
1946
+
1947
+ .. versionadded :: 2.4
1948
+ The expression functionality was introduced in Symfony 2.4.
1949
+
1950
+ In addition to a role like ``ROLE_ADMIN ``, the ``isGranted `` method also
1951
+ accepts an :class: `Symfony\\ Component\\ ExpressionLanguage\\ Expression ` object::
1952
+
1953
+ use Symfony\Component\Security\Core\Exception\AccessDeniedException;
1954
+ use Symfony\Component\ExpressionLanguage\Expression;
1955
+ // ...
1956
+
1957
+ public function indexAction()
1958
+ {
1959
+ if (!$this->get('security.context')->isGranted(new Expression(
1960
+ '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1961
+ ))) {
1962
+ throw new AccessDeniedException();
1963
+ }
1964
+
1965
+ // ...
1966
+ }
1967
+
1968
+ In this example, if the current user has ``ROLE_ADMIN `` or if the current
1969
+ user object's ``isSuperAdmin() `` method returns ``true ``, then access will
1970
+ be granted (note: your User object may not have an ``isSuperAdmin `` method,
1971
+ that method is invented for this example).
1972
+
1973
+ This uses an expression and you can learn more about the expression language
1974
+ syntax, see :doc: `/components/expression_language/syntax `.
1975
+
1976
+ .. _book-security-expression-variables :
1977
+
1978
+ Inside the expression, you have access to a number of variables:
1979
+
1980
+ * ``user `` The user object (or the string ``anon `` if you're not authenticated);
1981
+ * ``roles `` The array of roles the user has, including from the
1982
+ :ref: `role hierarchy <book-security-role-hierarchy >` but not including
1983
+ the ``IS_AUTHENTICATED_* `` attributes (see the functions below);
1984
+ * ``object ``: The object (if any) that's passed as the second argument to
1985
+ ``isGranted `` ;
1986
+ * ``token `` The token object;
1987
+ * ``trust_resolver ``: The :class: `Symfony\\ Component\\ Security\\ Core\\ Authentication\\ AuthenticationTrustResolverInterface `,
1988
+ object: you'll probably use the ``is_* `` functions below instead.
1989
+
1990
+ Additionally, you have access to a number of functions inside the expression:
1991
+
1992
+ * ``is_authenticated ``: Returns ``true `` if the user is authenticated via "remember-me"
1993
+ or authenticated "fully" - i.e. returns true if the user is "logged in";
1994
+ * ``is_anonymous ``: Equal to using ``IS_AUTHENTICATED_ANONYMOUSLY `` with
1995
+ the ``isGranted `` function;
1996
+ * ``is_remember_me ``: Similar, but not equal to ``IS_AUTHENTICATED_REMEMBERED ``,
1997
+ see below;
1998
+ * ``is_fully_authenticated ``: Similar, but not equal to ``IS_AUTHENTICATED_FULLY ``,
1999
+ see below;
2000
+ * ``has_role ``: Checks to see if the user has the given role - equivalent
2001
+ to an expression like ``'ROLE_ADMIN' in roles ``.
2002
+
2003
+ .. sidebar :: ``is_remember_me`` is different than checking ``IS_AUTHENTICATED_REMEMBERED``
2004
+
2005
+ The ``is_remember_me `` and ``is_authenticated_fully `` functions are *similar *
2006
+ to using ``IS_AUTHENTICATED_REMEMBERED `` and ``IS_AUTHENTICATED_FULLY ``
2007
+ with the ``isGranted `` function - but they are **not ** the same. The
2008
+ following shows the difference::
2009
+
2010
+ use Symfony\Component\ExpressionLanguage\Expression;
2011
+ // ...
2012
+
2013
+ $sc = $this->get('security.context');
2014
+ $access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED');
2015
+
2016
+ $access2 = $sc->isGranted(new Expression(
2017
+ 'is_remember_me() or is_fully_authenticated()'
2018
+ ));
2019
+
2020
+ Here, ``$access1 `` and ``$access2 `` will be the same value. Unlike the
2021
+ behavior of ``IS_AUTHENTICATED_REMEMBERED `` and ``IS_AUTHENTICATED_FULLY ``,
2022
+ the ``is_remember_me `` function *only * returns true if the user is authenticated
2023
+ via a remember-me cookie and ``is_fully_authenticated `` *only * returns
2024
+ true if the user has actually logged in during this session (i.e. is
2025
+ full-fledged).
2026
+
1859
2027
Impersonating a User
1860
2028
--------------------
1861
2029
0 commit comments