|
| 1 | +.. index:: |
| 2 | + single: Cache; CSRF; Forms |
| 3 | + |
| 4 | +Caching Pages that Contain CSRF Protected Forms |
| 5 | +=============================================== |
| 6 | + |
| 7 | +CSRF - or `Cross-site request forgery`_ - is a method by which a malicious |
| 8 | +user attempts to make your legitimate users unknowingly submit data that |
| 9 | +they don't intend to submit. Fortunately, CSRF attacks can be prevented by |
| 10 | +using a CSRF token inside your forms. |
| 11 | + |
| 12 | +For more information about how this protection works in Symfony, please |
| 13 | +check :ref:`CSRF Protection <forms-csrf>`. |
| 14 | + |
| 15 | +.. note:: |
| 16 | + |
| 17 | + A `Security CSRF Component`_ was introduced in Symfony 2.4 which provides |
| 18 | + a class CsrfTokenManager for generating and validating CSRF tokens |
| 19 | + |
| 20 | +Why Varnish does not cache by default these pages |
| 21 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 22 | + |
| 23 | +There are many ways to generate unique tokens for each user but in order get |
| 24 | +them validated when the form is submitted, you need to store them inside the |
| 25 | +PHP Session. |
| 26 | + |
| 27 | +If you are using Varnish or some similar reverse proxy cache and you try to cache |
| 28 | +pages containing forms with CSRF token protection, you will see that, by default, |
| 29 | +Varnish fails to cache them. |
| 30 | + |
| 31 | +This happens because a cookie is sent in order to preserve the PHP session open and |
| 32 | +Varnish default behaviour is to not cache HTTP requests with cookies. |
| 33 | + |
| 34 | +If you think about it, if you managed to cache the form you would end up |
| 35 | +with many users getting the same token in the form generation. When these |
| 36 | +users try to send the form to the server, the CSRF validation will fail for |
| 37 | +them because the expected token is based on the session id and different |
| 38 | +for each user. |
| 39 | + |
| 40 | +How to cache most of the page and still be able to use CSRF protection |
| 41 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 42 | + |
| 43 | +In case the HTML page where the protected form appears is heavy to load, you |
| 44 | +can use more advanced caching techniques like `ESI`_ fragments, having a TTL for |
| 45 | +the full page and embedding the form inside an ESI tag with no cache at all. |
| 46 | + |
| 47 | +Another option to be able to cache that heavy page would be loading the form |
| 48 | +via an uncached AJAX request but cache the rest of the HTML response. |
| 49 | + |
| 50 | +Or you can even load just the CSRF token with an AJAX request and replace the |
| 51 | +form field value with it. |
| 52 | + |
| 53 | +.. _`ESI`: http://www.w3.org/TR/esi-lang |
| 54 | +.. _`Security CSRF Component`: https://github.com/symfony/security-csrf |
0 commit comments