diff --git a/_build/redirection_map b/_build/redirection_map index f42bde6b892..6d142e7104d 100644 --- a/_build/redirection_map +++ b/_build/redirection_map @@ -401,3 +401,4 @@ /weblink /web_link /components/weblink /components/web_link /frontend/encore/installation-no-flex /frontend/encore/installation +/http_cache/form_csrf_caching /security/csrf diff --git a/forms.rst b/forms.rst index bf0d787782d..f922785a304 100644 --- a/forms.rst +++ b/forms.rst @@ -714,7 +714,7 @@ Learn more /form/* /controller/upload_file /reference/forms/types - /http_cache/form_csrf_caching + /security/csrf .. _`Symfony Form component`: https://github.com/symfony/form .. _`DateTime`: https://php.net/manual/en/class.datetime.php diff --git a/http_cache/form_csrf_caching.rst b/http_cache/form_csrf_caching.rst deleted file mode 100644 index 41aba4c0eab..00000000000 --- a/http_cache/form_csrf_caching.rst +++ /dev/null @@ -1,43 +0,0 @@ -.. index:: - single: Cache; CSRF; Forms - -Caching Pages that Contain CSRF Protected Forms -=============================================== - -CSRF tokens are meant to be different for every user. This is why you -need to be cautious if you try to cache pages with forms including them. - -For more information about how CSRF protection works in Symfony, please -check :doc:`CSRF Protection `. - -Why Caching Pages with a CSRF token is Problematic --------------------------------------------------- - -Typically, each user is assigned a unique CSRF token, which is stored in -the session for validation. This means that if you *do* cache a page with -a form containing a CSRF token, you'll cache the CSRF token of the *first* -user only. When a user submits the form, the token won't match the token -stored in the session and all users (except for the first) will fail CSRF -validation when submitting the form. - -In fact, many reverse proxies (like Varnish) will refuse to cache a page -with a CSRF token. This is because a cookie is sent in order to preserve -the PHP session open and Varnish's default behavior is to not cache HTTP -requests with cookies. - -How to Cache Most of the Page and still be able to Use CSRF Protection ----------------------------------------------------------------------- - -To cache a page that contains a CSRF token, you can use more advanced caching -techniques like :doc:`ESI fragments `, where you cache the full -page and embedding the form inside an ESI tag with no cache at all. - -Another option would be to load the form via an uncached AJAX request, but -cache the rest of the HTML response. - -Or you can even load just the CSRF token with an AJAX request and replace the -form field value with it. Take a look at :doc:`hinclude.js ` -for a nice solution. - -.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery -.. _`Security CSRF Component`: https://github.com/symfony/security-csrf diff --git a/http_cache/varnish.rst b/http_cache/varnish.rst index b98390e385b..77494acb979 100644 --- a/http_cache/varnish.rst +++ b/http_cache/varnish.rst @@ -65,7 +65,7 @@ at least for some parts of the site, e.g. when using forms with :doc:`CSRF Protection `. In this situation, make sure to :doc:`only start a session when actually needed ` and clear the session when it is no longer needed. Alternatively, you can look -into :doc:`/http_cache/form_csrf_caching`. +into :doc:`/security/csrf`. Cookies created in JavaScript and used only in the frontend, e.g. when using Google Analytics, are nonetheless sent to the server. These cookies are not diff --git a/performance.rst b/performance.rst index 01abce429c1..25491cd6199 100644 --- a/performance.rst +++ b/performance.rst @@ -138,7 +138,6 @@ Learn more ---------- * :doc:`/http_cache/varnish` -* :doc:`/http_cache/form_csrf_caching` .. _`byte code caches`: https://en.wikipedia.org/wiki/List_of_PHP_accelerators .. _`OPcache`: https://php.net/manual/en/book.opcache.php diff --git a/security/csrf.rst b/security/csrf.rst index 80f1f6c9d6b..023fbe157ea 100644 --- a/security/csrf.rst +++ b/security/csrf.rst @@ -55,6 +55,22 @@ for more information): 'csrf_protection' => null, )); +The tokens used for CSRF protection are meant to be different for every user and +they are stored in the session. That's why a session is started automatically as +soon as you render a form with CSRF protection. + +.. _caching-pages-that-contain-csrf-protected-forms: + +Moreover, this means that you cannot fully cache pages that include CSRF +protected forms. As an alternative, you can: + +* Embed the form inside an uncached :doc:`ESI fragment ` and + cache the rest of the page contents; +* Cache the entire page and load the form via an uncached AJAX request; +* Cache the entire page and use :doc:`hinclude.js ` to + load just the CSRF token with an uncached AJAX request and replace the form + field value with it. + CSRF Protection in Symfony Forms -------------------------------- @@ -92,17 +108,6 @@ this can be customized on a form-by-form basis:: // ... } -.. caution:: - - Since the token is stored in the session, a session is started automatically - as soon as you render a form with CSRF protection. - -.. caution:: - - CSRF tokens are meant to be different for every user. Beware of that when - caching pages that include forms containing CSRF tokens. For more - information, see :doc:`/http_cache/form_csrf_caching`. - CSRF Protection in Login Forms ------------------------------ @@ -113,6 +118,7 @@ CSRF Protection in HTML Forms ----------------------------- .. versionadded:: 4.1 + In Symfony versions prior to 4.1, CSRF support required installing the Symfony Form component even if you didn't use it.