-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Final additions: Expression language framework docs #3258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
ac15bf5
be86fef
d72759a
33676dc
0cf1828
bc22f16
0000250
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -864,6 +864,8 @@ options: | |
(internally, an :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` | ||
is thrown); | ||
|
||
* ``allow_if`` If the expression returns false, then access is denied; | ||
|
||
* ``requires_channel`` If the incoming request's channel (e.g. ``http``) | ||
does not match this value (e.g. ``https``), the user will be redirected | ||
(e.g. redirected from ``http`` to ``https``, or vice versa). | ||
|
@@ -951,6 +953,58 @@ address): | |
|
||
* The second access rule is not examined as the first rule matched. | ||
|
||
.. _book-security-allow-if: | ||
|
||
Securing by an Expression | ||
~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. versionadded:: 2.4 | ||
The ``allow_if`` functionality was introduced in Symfony 2.4. | ||
|
||
Once an ``access_control`` entry is matched, you can deny access via the | ||
``roles`` key or use more complex logic with an expression in the ``allow_if`` | ||
key: | ||
|
||
.. configuration-block:: | ||
|
||
.. code-block:: yaml | ||
|
||
# app/config/security.yml | ||
security: | ||
# ... | ||
access_control: | ||
- | ||
path: ^/_internal/secure | ||
allow_if: "'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" | ||
|
||
.. code-block:: xml | ||
|
||
<access-control> | ||
<rule path="^/_internal/secure" | ||
allow-if="'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" /> | ||
</access-control> | ||
|
||
.. code-block:: php | ||
|
||
'access_control' => array( | ||
array( | ||
'path' => '^/_internal/secure', | ||
'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")', | ||
), | ||
), | ||
|
||
In this case, when the user tries to access any URL starting with ``/_internal/secure``, | ||
she will only be granted access if the IP address is ``127.0.0.1`` or if | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. she -> they There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks :) |
||
the user has the ``ROLE_ADMIN`` role. | ||
|
||
Inside the expression, you have access to a number of different variables | ||
and functions including ``request``, which is the Symfony | ||
:class:`Symfony\\Component\\HttpFoundation\\Request` object (see | ||
:ref:`component-http-foundation-request`). | ||
|
||
For a list of the other functions and variables, see | ||
:ref:`functions and variables <book-security-expression-variables>`. | ||
|
||
.. _book-security-securing-channel: | ||
|
||
Securing by Channel | ||
|
@@ -1656,6 +1710,8 @@ doesn't need to be defined anywhere - you can just start using it. | |
Symfony2. If you define your own roles with a dedicated ``Role`` class | ||
(more advanced), don't use the ``ROLE_`` prefix. | ||
|
||
.. _book-security-role-hierarchy: | ||
|
||
Hierarchical Roles | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
|
@@ -1834,6 +1890,31 @@ the built-in helper function: | |
idea to have a main firewall that covers all URLs (as has been shown | ||
in this chapter). | ||
|
||
.. _book-security-template-expression: | ||
|
||
.. versionadded:: 2.4 | ||
The ``expression`` functionality was introduced in Symfony 2.4. | ||
|
||
You can also use expressions inside your templates: | ||
|
||
.. configuration-block:: | ||
|
||
.. code-block:: html+jinja | ||
|
||
{% if is_granted(expression('has_role("ROLE_ADMIN")')) %} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should provide examples which clearly shows the advantages of the expressions on complex situations. In this case, you can simply call |
||
<a href="...">Delete</a> | ||
{% endif %} | ||
|
||
.. code-block:: html+php | ||
|
||
<?php if ($view['security']->isGranted(new Expression( | ||
'has_role("ROLE_ADMIN")' | ||
))): ?> | ||
<a href="...">Delete</a> | ||
<?php endif; ?> | ||
|
||
For more details on expressions and security, see :ref:`book-security-expressions`. | ||
|
||
Access Control in Controllers | ||
----------------------------- | ||
|
||
|
@@ -1856,6 +1937,91 @@ method of the security context:: | |
A firewall must be active or an exception will be thrown when the ``isGranted`` | ||
method is called. See the note above about templates for more details. | ||
|
||
.. _book-security-expressions: | ||
|
||
Complex Access Controls with Expressions | ||
---------------------------------------- | ||
|
||
.. versionadded:: 2.4 | ||
The expression functionality was introduced in Symfony 2.4. | ||
|
||
In addition to a role like ``ROLE_ADMIN``, the ``isGranted`` method also | ||
accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: | ||
|
||
use Symfony\Component\Security\Core\Exception\AccessDeniedException; | ||
use Symfony\Component\ExpressionLanguage\Expression; | ||
// ... | ||
|
||
public function indexAction() | ||
{ | ||
if (!$this->get('security.context')->isGranted(new Expression( | ||
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' | ||
))) { | ||
throw new AccessDeniedException(); | ||
} | ||
|
||
// ... | ||
} | ||
|
||
In this example, if the current user has ``ROLE_ADMIN`` or if the current | ||
user object's ``isSuperAdmin`` method returns ``true``, then access will | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
be granted (note: your User object may not have an ``isSuperAdmin`` method, | ||
that method is invented for this example). This uses an expression and you | ||
can learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to put this sentence in the section below (you didn't put the reference in the other examples of the security) |
||
|
||
.. _book-security-expression-variables: | ||
|
||
Inside the expression, you have access to a number of variables: | ||
|
||
* ``user`` The user object (or the string ``anon`` if you're not authenticated); | ||
* ``roles`` The array of roles the user has, including from the | ||
:ref:`role hierarchy <book-security-role-hierarchy>` but not including | ||
the ``IS_AUTHENTICATED_*`` attributes (see the functions below); | ||
* ``object``: The object (if any) that's passed as the second argument to | ||
``isGranted`` ; | ||
* ``token`` The token object; | ||
* ``trust_resolver``: The :class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface`, | ||
object: you'll probably use the ``is_*`` functions below instead. | ||
|
||
Additionally, you have access to a number of functions inside the expression. | ||
**Note**: some of these functions *look* similar to the ``IS_AUTHENTICATED_*`` | ||
attributes, but work differently. See the note below: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it really needed to have 2 notes? Maybe just a caution directive? |
||
|
||
* ``is_authenticated``: Returns true if the user is authenticated via "remember-me" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true should be inside a literal |
||
or authenticated "fully" - i.e. returns true if the user is "logged in"; | ||
* ``is_anonymous``: Equal to using ``IS_AUTHENTICATED_ANONYMOUSLY`` with | ||
the ``isGranted`` function; | ||
* ``is_remember_me``: Similar, but not equal to ``IS_AUTHENTICATED_REMEMBERED``, | ||
see below; | ||
* ``is_fully_authenticated``: Similar, but not equal to ``IS_AUTHENTICATED_FULLY``, | ||
see below; | ||
* ``has_role``: Checks to see if the user has the given role - equivalent | ||
to an expression like ``'ROLE_ADMIN' in roles``. | ||
|
||
.. sidebar:: ``is_remember_me`` is different than checking ``IS_AUTHENTICATED_REMEMBERED`` | ||
|
||
The ``is_remember_me`` and ``is_authenticated_fully`` functions are *similar* | ||
to using ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY`` | ||
with the ``isGranted`` function - but they are **not** the same. The | ||
following shows the difference:: | ||
|
||
use Symfony\Component\ExpressionLanguage\Expression; | ||
// ... | ||
|
||
$sc = $this->get('security.context'); | ||
$access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED'); | ||
|
||
$access2 = $sc->isGranted(new Expression( | ||
'is_remember_me() or is_fully_authenticated()' | ||
)); | ||
|
||
Here, ``$access1`` and ``$access2`` will be the same value. Unlike the | ||
behavior of ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``, | ||
the ``is_remember_me`` function *only* returns true if the user is authenticated | ||
via a remember-me cookie and ``is_fully_authenticated`` *only* returns | ||
true if the user has actually logged in during this session (i.e. is | ||
full-fledged). | ||
|
||
Impersonating a User | ||
-------------------- | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.. index:: | ||
single: Expressions in the Framework | ||
|
||
How to use Expressions in Security, Routing, Services, and Validation | ||
===================================================================== | ||
|
||
.. versionadded:: 2.4 | ||
The expression functionality was introduced in Symfony 2.4. | ||
|
||
In Symfony 2.4, a powerful :doc:`ExpressionLanguage </components/expression_language/introduction>` | ||
component was added to Symfony. This allows us to add highly customized | ||
logic inside configuration. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wonder if we should add a note on how to use or inject expressions, if need be, to other services besides these explicit here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think over time we will start to think of other uses for the expression language, and when we do, we should certainly add more cookbook entries. But fortunately, for right now, we just need to make sure the basic docs are present. |
||
|
||
The Symfony Framework leverages expressions out of the box in the following | ||
ways: | ||
|
||
* :ref:`Configuring services <book-services-expressions>`; | ||
* :ref:`Route matching conditions <book-routing-conditions>`; | ||
* :ref:`Checking security <book-security-expressions>` and | ||
:ref:`access controls with allow_if <book-security-allow-if>`; | ||
* :doc:`Validation </reference/constraints/Expression>`. | ||
|
||
For more information about how to create and work with expressions, see | ||
:doc:`/components/expression_language/syntax`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. php-cs-fixer |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Expressions | ||
=========== | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, they are not regular expressions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requirements
in routes are regular expressions, or am I missing something?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, maybe the sentence is confusing :) "to match only certain routing wildcards" I thought you meaned the
path
option, not therequirements
option