Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch '2.1'

  • Loading branch information...
commit 279a6b9ecfc2f52f2bc9ec06be4990961e39c036 2 parents 1cf2081 + b7d4d46
Ryan Weaver weaverryan authored
9 book/_security-2012-6431.rst.inc
View
@@ -0,0 +1,9 @@
+.. note::
+
+ Since Symfony 2.0.20/2.1.5, the Twig ``render`` tag now takes an absolute url
+ instead of a controller logical path. This fixes an important security
+ issue (`CVE-2012-6431`_) reported on the official blog. If your application
+ uses an older version of Symfony or still uses the previous ``render`` tag
+ syntax, you should upgrade as soon as possible.
+
+.. _`CVE-2012-6431`: http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released
95 book/http_cache.rst
View
@@ -881,17 +881,50 @@ matter), Symfony2 uses the standard ``render`` helper to configure ESI tags:
.. code-block:: jinja
- {% render '...:news' with {}, {'standalone': true} %}
+ {% render url('latest_news', { 'max': 5 }), {'standalone': true} %}
.. code-block:: php
- <?php echo $view['actions']->render('...:news', array(), array('standalone' => true)) ?>
+ <?php echo $view['actions']->render(
+ $view['router']->generate('latest_news', array('max' => 5), true),
+ array('standalone' => true)
+ ) ?>
-By setting ``standalone`` to ``true``, you tell Symfony2 that the action
-should be rendered as an ESI tag. You might be wondering why you would want to
-use a helper instead of just writing the ESI tag yourself. That's because
-using a helper makes your application work even if there is no gateway cache
-installed.
+.. include:: /book/_security-2012-6431.rst.inc
+
+The ``render`` tag takes the absolute url to the embedded action. This means
+that you need to define a new route to the controller that you're embedding:
+
+.. code-block:: yaml
+
+ # app/config/routing.yml
+ latest_news:
+ pattern: /esi/latest-news/{max}
+ defaults: { _controller: AcmeNewsBundle:News:news }
+ requirements: { max: \d+ }
+
+.. caution::
+
+ Unless you want this URL to be accessible to the outside world, you
+ should use Symfony's firewall to secure it (by allowing access to your
+ reverse proxy's IP range). See the :ref:`Securing by IP<book-security-securing-ip>`
+ section of the :doc:`Security Chapter </book/security>` for more information
+ on how to do this.
+
+.. tip::
+
+ The best practice is to mount all your ESI urls on a single prefix (e.g.
+ ``/esi``) of your choice. This has two main advantages. First, it eases
+ the management of ESI urls as you can easily identify the routes used for ESI.
+ Second, it eases security management since securing all urls starting
+ with the same prefix is easier than securing each individual url. See
+ the above note for more details on securing ESI URLs.
+
+By setting ``standalone`` to ``true`` in the ``render`` Twig tag, you tell
+Symfony2 that the action should be rendered as an ESI tag. You might be
+wondering why you would want to use a helper instead of just writing the ESI tag
+yourself. That's because using a helper makes your application work even if
+there is no gateway cache installed.
When standalone is ``false`` (the default), Symfony2 merges the included page
content within the main one before sending the response to the client. But
@@ -912,7 +945,7 @@ of the master page.
.. code-block:: php
- public function newsAction()
+ public function newsAction($max)
{
// ...
@@ -922,52 +955,6 @@ of the master page.
With ESI, the full page cache will be valid for 600 seconds, but the news
component cache will only last for 60 seconds.
-A requirement of ESI, however, is that the embedded action be accessible
-via a URL so the gateway cache can fetch it independently of the rest of
-the page. Of course, an action can't be accessed via a URL unless it has
-a route that points to it. Symfony2 takes care of this via a generic route
-and controller. For the ESI include tag to work properly, you must define
-the ``_internal`` route:
-
-.. configuration-block::
-
- .. code-block:: yaml
-
- # app/config/routing.yml
- _internal:
- resource: "@FrameworkBundle/Resources/config/routing/internal.xml"
- prefix: /_internal
-
- .. code-block:: xml
-
- <!-- app/config/routing.xml -->
- <?xml version="1.0" encoding="UTF-8" ?>
-
- <routes xmlns="http://symfony.com/schema/routing"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
-
- <import resource="@FrameworkBundle/Resources/config/routing/internal.xml" prefix="/_internal" />
- </routes>
-
- .. code-block:: php
-
- // app/config/routing.php
- use Symfony\Component\Routing\RouteCollection;
- use Symfony\Component\Routing\Route;
-
- $collection->addCollection($loader->import('@FrameworkBundle/Resources/config/routing/internal.xml', '/_internal'));
-
- return $collection;
-
-.. tip::
-
- Since this route allows all actions to be accessed via a URL, you might
- want to protect it by using the Symfony2 firewall feature (by allowing
- access to your reverse proxy's IP range). See the :ref:`Securing by IP<book-security-securing-ip>`
- section of the :doc:`Security Chapter </book/security>` for more information
- on how to do this.
-
One great advantage of this caching strategy is that you can make your
application as dynamic as needed and at the same time, hit the application as
little as possible.
24 book/security.rst
View
@@ -755,14 +755,16 @@ Securing by IP
~~~~~~~~~~~~~~
Certain situations may arise when you may need to restrict access to a given
-route based on IP. This is particularly relevant in the case of :ref:`Edge Side Includes<edge-side-includes>`
-(ESI), for example, which utilize a route named "_internal". When
-ESI is used, the _internal route is required by the gateway cache to enable
-different caching options for subsections within a given page. This route
-comes with the ^/_internal prefix by default in the standard edition (assuming
-you've uncommented those lines from the routing file).
+route based on IP. This is particularly relevant in the case of
+:ref:`Edge Side Includes<edge-side-includes>` (ESI), for example. When ESI is
+enabled, it's recommended to secure access to ESI URLs. Indeed, some ESI may
+contain some private contents like the current logged in user's information. To
+prevent any direct access to these resources from a web browser by guessing the
+URL pattern, the ESI route must be secured to be only visible from the trusted
+reverse proxy cache.
-Here is an example of how you might secure this route from outside access:
+Here is an example of how you might secure all ESI routes that start with a
+given prefix, ``/esi``, from outside access:
.. configuration-block::
@@ -772,22 +774,24 @@ Here is an example of how you might secure this route from outside access:
security:
# ...
access_control:
- - { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
+ - { path: ^/esi, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
.. code-block:: xml
<access-control>
- <rule path="^/_internal" role="IS_AUTHENTICATED_ANONYMOUSLY" ip="127.0.0.1" />
+ <rule path="^/esi" role="IS_AUTHENTICATED_ANONYMOUSLY" ip="127.0.0.1" />
</access-control>
.. code-block:: php
'access_control' => array(
- array('path' => '^/_internal', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'ip' => '127.0.0.1'),
+ array('path' => '^/esi', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'ip' => '127.0.0.1'),
),
.. _book-security-securing-channel:
+.. include:: /book/_security-2012-6431.rst.inc
+
Securing by Channel
~~~~~~~~~~~~~~~~~~~
54 book/templating.rst
View
@@ -623,8 +623,43 @@ The ``recentList`` template is perfectly straightforward:
(e.g. ``/article/*slug*``). This is a bad practice. In the next section,
you'll learn how to do this correctly.
-To include the controller, you'll need to refer to it using the standard string
-syntax for controllers (i.e. **bundle**:**controller**:**action**):
+Even though this controller will only be used internally, you'll need to
+create a route that points to the controller:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ latest_articles:
+ pattern: /articles/latest/{max}
+ defaults: { _controller: AcmeArticleBundle:Article:recentArticles }
+
+ .. code-block:: xml
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+
+ <routes xmlns="http://symfony.com/schema/routing"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
+
+ <route id="latest_articles" pattern="/articles/latest/{max}">
+ <default key="_controller">AcmeArticleBundle:Article:recentArticles</default>
+ </route>
+ </routes>
+
+ .. code-block:: php
+
+ use Symfony\Component\Routing\RouteCollection;
+ use Symfony\Component\Routing\Route;
+
+ $collection = new RouteCollection();
+ $collection->add('latest_articles', new Route('/articles/latest/{max}', array(
+ '_controller' => 'AcmeArticleBundle:Article:recentArticles',
+ )));
+
+ return $collection;
+
+To include the controller, you'll need to refer to it using an absolute url:
.. configuration-block::
@@ -634,7 +669,7 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**):
{# ... #}
<div id="sidebar">
- {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %}
+ {% render url('latest_articles', { 'max': 3 }) %}
</div>
.. code-block:: html+php
@@ -643,9 +678,13 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**):
<!-- ... -->
<div id="sidebar">
- <?php echo $view['actions']->render('AcmeArticleBundle:Article:recentArticles', array('max' => 3)) ?>
+ <?php echo $view['actions']->render(
+ $view['router']->generate('latest_articles', array('max' => 3), true)
+ ) ?>
</div>
+.. include:: /book/_security-2012-6431.rst.inc
+
Whenever you find that you need a variable or a piece of information that
you don't have access to in a template, consider rendering a controller.
Controllers are fast to execute and promote good code organization and reuse.
@@ -664,11 +703,14 @@ Symfony2 uses the standard ``render`` helper to configure ``hinclude`` tags:
.. code-block:: jinja
- {% render '...:news' with {}, {'standalone': 'js'} %}
+ {% render url('...'), {'standalone': 'js'} %}
.. code-block:: php
- <?php echo $view['actions']->render('...:news', array(), array('standalone' => 'js')) ?>
+ <?php echo $view['actions']->render(
+ $view['router']->generate('...'),
+ array('standalone' => 'js')
+ ) ?>
.. note::
58 quick_tour/the_view.rst
View
@@ -180,18 +180,57 @@ And what if you want to embed the result of another controller in a template?
That's very useful when working with Ajax, or when the embedded template needs
some variable not available in the main template.
-Suppose you've created a ``fancy`` action, and you want to include it inside
-the ``index`` template. To do this, use the ``render`` tag:
+Suppose you've created a ``fancyAction`` controller method, and you want to "render"
+it inside the ``index`` template. First, create a route to your new controller
+in one of your application's routing configuration files.
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/routing.yml
+ fancy:
+ pattern: /included/fancy/{name}/{color}
+ defaults: { _controller: AcmeDemoBundle:Demo:fancy }
+
+ .. code-block:: xml
+
+ <!-- app/config/routing.xml -->
+ <?xml version="1.0" encoding="UTF-8" ?>
+ <routes xmlns="http://symfony.com/schema/routing"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
+
+ <route id="fancy" pattern="/included/fancy/{name}/{color}">
+ <default key="_controller">AcmeDemoBundle:Demo:fancy</default>
+ </route>
+ </routes>
+
+ .. code-block:: php
+
+ // app/config/routing.php
+ use Symfony\Component\Routing\RouteCollection;
+ use Symfony\Component\Routing\Route;
+
+ $collection = new RouteCollection();
+ $collection->add('fancy', new Route('/included/fancy/{name}/{color}', array(
+ '_controller' => 'AcmeDemoBundle:Demo:fancy',
+ )));
+
+ return $collection;
+
+To include the result (e.g. ``HTML``) of the controller, use the ``render`` tag:
.. code-block:: jinja
{# src/Acme/DemoBundle/Resources/views/Demo/index.html.twig #}
- {% render "AcmeDemoBundle:Demo:fancy" with {'name': name, 'color': 'green'} %}
+ {% render url('fancy', { 'name': name, 'color': 'green'}) %}
+
+.. include:: /book/_security-2012-6431.rst.inc
-Here, the ``AcmeDemoBundle:Demo:fancy`` string refers to the ``fancy`` action
-of the ``Demo`` controller. The arguments (``name`` and ``color``) act like
-simulated request variables (as if the ``fancyAction`` were handling a whole
-new request) and are made available to the controller::
+The ``render`` tag will execute the ``AcmeDemoBundle:Demo:fancy`` controller
+and include its result. For example, your new ``fancyAction`` might look
+like this::
// src/Acme/DemoBundle/Controller/DemoController.php
@@ -202,7 +241,10 @@ new request) and are made available to the controller::
// create some object, based on the $color variable
$object = ...;
- return $this->render('AcmeDemoBundle:Demo:fancy.html.twig', array('name' => $name, 'object' => $object));
+ return $this->render('AcmeDemoBundle:Demo:fancy.html.twig', array(
+ 'name' => $name,
+ 'object' => $object
+ ));
}
// ...
5 reference/twig_reference.rst
View
@@ -113,8 +113,9 @@ Tags
+---------------------------------------------------+-------------------------------------------------------------------+
| Tag Syntax | Usage |
+===================================================+===================================================================+
-| ``{% render 'controller' with {parameters} %}`` | This will render the Response Content for the given controller, |
-| | more information in :ref:`templating-embedding-controller`. |
+| ``{% render url('route', {parameters}) %}`` | This will render the Response Content for the given controller |
+| | that the URL points to. For more information, |
+| | see :ref:`templating-embedding-controller`. |
+---------------------------------------------------+-------------------------------------------------------------------+
| ``{% form_theme form 'file' %}`` | This will look inside the given file for overridden form blocks, |
| | more information in :doc:`/cookbook/form/form_customization`. |
Please sign in to comment.
Something went wrong with that request. Please try again.