Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 42d2b15

Browse filesBrowse files
committed
Merge branch '2.7'
* 2.7: Re-wording based on Wouter's recommendation update text to use SetHandler (not ProxyPassMatch) cache_csrf_form [Book][Security] Add isPasswordValid doc as in 2.6 [#4656] Re-reading private service section Update code example to fit description
2 parents 6f9832d + e5a6c7c commit 42d2b15
Copy full SHA for 42d2b15

File tree

Expand file treeCollapse file tree

7 files changed

+84
-34
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+84
-34
lines changed

‎book/forms.rst

Copy file name to clipboardExpand all lines: book/forms.rst
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,13 @@ section.
17861786
The ``intention`` option is optional but greatly enhances the security of
17871787
the generated token by making it different for each form.
17881788

1789+
.. caution::
1790+
1791+
CSRF tokens are meant to be different for every user. This is why you
1792+
need to be cautious if you try to cache pages with forms including this
1793+
kind of protection. For more information, see
1794+
:doc:`/cookbook/cache/form_csrf_caching`.
1795+
17891796
.. index::
17901797
single: Forms; With no class
17911798

@@ -1921,6 +1928,8 @@ Learn more from the Cookbook
19211928
* :doc:`/cookbook/form/form_customization`
19221929
* :doc:`/cookbook/form/dynamic_form_modification`
19231930
* :doc:`/cookbook/form/data_transformers`
1931+
* :doc:`/cookbook/security/csrf_in_login_form`
1932+
* :doc:`/cookbook/cache/form_csrf_caching`
19241933

19251934
.. _`Symfony Form component`: https://github.com/symfony/Form
19261935
.. _`DateTime`: http://php.net/manual/en/class.datetime.php

‎book/security.rst

Copy file name to clipboardExpand all lines: book/security.rst
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,8 +1174,8 @@ in the following way from a controller::
11741174
// whatever *your* User object is
11751175
$user = new AppBundle\Entity\User();
11761176
$plainPassword = 'ryanpass';
1177-
$encoded = $this->container->get('security.password_encoder')
1178-
->encodePassword($user, $plainPassword);
1177+
$encoder = $this->container->get('security.password_encoder');
1178+
$encoded = $encoder->encodePassword($user, $plainPassword);
11791179

11801180
$user->setPassword($encoded);
11811181

‎components/dependency_injection/advanced.rst

Copy file name to clipboardExpand all lines: components/dependency_injection/advanced.rst
+17-19Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,19 @@ Marking Services as public / private
1010
When defining services, you'll usually want to be able to access these definitions
1111
within your application code. These services are called ``public``. For example,
1212
the ``doctrine`` service registered with the container when using the DoctrineBundle
13-
is a public service as you can access it via::
13+
is a public service. This means that you can fetch it from the container
14+
using the ``get()`` method::
1415

1516
$doctrine = $container->get('doctrine');
1617

17-
However, there are use-cases when you don't want a service to be public. This
18-
is common when a service is only defined because it could be used as an
19-
argument for another service.
18+
In some cases, a service *only* exists to be injected into another service
19+
and is *not* intended to be fetched directly from the container as shown
20+
above.
2021

2122
.. _inlined-private-services:
2223

23-
Since a container is not able to detect if a service is retrieved from inside
24-
the container or the outside, a private service may still be retrieved using
25-
the ``get()`` method.
26-
27-
What makes private services special, is that they are converted from services
28-
to inlined instantiation (e.g. ``new PrivateThing()``) when they are only
29-
injected once, to increase the container performance. This means that you can
30-
never be sure if a private service exists in the container.
31-
32-
Simply said: A service will be private when you do not want to access it
33-
directly from your code.
34-
35-
Here is an example:
24+
In these cases, to get a minor performance boost, you can set the service
25+
to be *not* public (i.e. private):
3626

3727
.. configuration-block::
3828

@@ -63,11 +53,19 @@ Here is an example:
6353
$definition->setPublic(false);
6454
$container->setDefinition('foo', $definition);
6555
66-
Now that the service is private, you *should not* call (should not means, this
67-
*might* fail, see the explaination above)::
56+
What makes private services special is that, if they are only injected once,
57+
they are converted from services to inlined instantiations (e.g. ``new PrivateThing()``).
58+
This increases the container's performance.
59+
60+
Now that the service is private, you *should not* fetch the service directly
61+
from the container::
6862

6963
$container->get('foo');
7064

65+
This *may or may not work*, depending on if the service could be inlined.
66+
Simply said: A service can be marked as private if you do not want to access
67+
it directly from your code.
68+
7169
However, if a service has been marked as private, you can still alias it (see
7270
below) to access this service (via the alias).
7371

‎cookbook/cache/form_csrf_caching.rst

Copy file name to clipboard
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.. index::
2+
single: Cache; CSRF; Forms
3+
4+
Caching Pages that Contain CSRF Protected Forms
5+
===============================================
6+
7+
CSRF tokens are meant to be different for every user. This is why you
8+
need to be cautious if you try to cache pages with forms including them.
9+
10+
For more information about how CSRF protection works in Symfony, please
11+
check :ref:`CSRF Protection <forms-csrf>`.
12+
13+
Why Reverse Proxy Caches do not Cache these Pages by Default
14+
------------------------------------------------------------
15+
16+
There are many ways to generate unique tokens for each user but in order get
17+
them validated when the form is submitted, you need to store them inside the
18+
PHP Session.
19+
20+
If you are using Varnish or some similar reverse proxy cache and you try to cache
21+
pages containing forms with CSRF token protection, you will see that, by default,
22+
the reverse proxy cache refuses to cache.
23+
24+
This happens because a cookie is sent in order to preserve the PHP session open and
25+
Varnish default behaviour is to not cache HTTP requests with cookies.
26+
27+
If you think about it, if you managed to cache the form you would end up
28+
with many users getting the same token in the form generation. When these
29+
users try to send the form to the server, the CSRF validation will fail for
30+
them because the expected token is stored in their session and different
31+
for each user.
32+
33+
How to Cache Most of the Page and still Be Able to Use CSRF Protection
34+
----------------------------------------------------------------------
35+
36+
To cache a page that contains a CSRF token you can use more advanced caching
37+
techniques like `ESI`_ fragments, having a TTL for the full page and embedding
38+
the form inside an ESI tag with no cache at all.
39+
40+
Another option to be able to cache that heavy page would be loading the form
41+
via an uncached AJAX request but cache the rest of the HTML response.
42+
43+
Or you can even load just the CSRF token with an AJAX request and replace the
44+
form field value with it.
45+
46+
.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery
47+
.. _`ESI`: http://www.w3.org/TR/esi-lang
48+
.. _`Security CSRF Component`: https://github.com/symfony/security-csrf

‎cookbook/cache/index.rst

Copy file name to clipboardExpand all lines: cookbook/cache/index.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ Cache
55
:maxdepth: 2
66

77
varnish
8+
form_csrf_caching

‎cookbook/configuration/web_server_configuration.rst

Copy file name to clipboardExpand all lines: cookbook/configuration/web_server_configuration.rst
+6-13Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Using mod_proxy_fcgi with Apache 2.4
118118
If you are running Apache 2.4, you can easily use ``mod_proxy_fcgi`` to pass
119119
incoming requests to PHP-FPM. Configure PHP-FPM to listen on a TCP socket
120120
(``mod_proxy`` currently `does not support unix sockets`_), enable ``mod_proxy``
121-
and ``mod_proxy_fcgi`` in your Apache configuration and use the ``ProxyPassMatch``
121+
and ``mod_proxy_fcgi`` in your Apache configuration and use the ``SetHandler``
122122
directive to pass requests for PHP files to PHP FPM:
123123

124124
.. code-block:: apache
@@ -133,14 +133,17 @@ directive to pass requests for PHP files to PHP FPM:
133133
# SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
134134
135135
# For Apache 2.4.9 or higher
136-
# Using SetHandler avoids issues with using ProxyPassMatch in combination
136+
# Using SetHandler avoids issues with using ProxyPassMatch in combination
137137
# with mod_rewrite or mod_autoindex
138138
<FilesMatch \.php$>
139139
SetHandler proxy:fcgi://127.0.0.1:9000
140140
</FilesMatch>
141141
# If you use Apache version below 2.4.9 you must consider update or use this instead
142142
# ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/web/$1
143-
143+
# If you run your Symfony application on a subpath of your document root, the
144+
# regular expression must be changed accordingly:
145+
# ProxyPassMatch ^/path-to-app/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/web/$1
146+
144147
DocumentRoot /var/www/project/web
145148
<Directory /var/www/project/web>
146149
# enable the .htaccess rewrites
@@ -152,16 +155,6 @@ directive to pass requests for PHP files to PHP FPM:
152155
CustomLog /var/log/apache2/project_access.log combined
153156
</VirtualHost>
154157
155-
.. caution::
156-
157-
When you run your Symfony application on a subpath of your document root,
158-
the regular expression used in ``ProxyPassMatch`` directive must be changed
159-
accordingly:
160-
161-
.. code-block:: apache
162-
163-
ProxyPassMatch ^/path-to-app/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/web/$1
164-
165158
PHP-FPM with Apache 2.2
166159
~~~~~~~~~~~~~~~~~~~~~~~
167160

‎cookbook/map.rst.inc

Copy file name to clipboardExpand all lines: cookbook/map.rst.inc
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* :doc:`/cookbook/cache/index`
2121

2222
* :doc:`/cookbook/cache/varnish`
23+
* :doc:`/cookbook/cache/form_csrf_caching`
2324

2425
* **Composer**
2526

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.