|
| 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 | +Why Varnish does not Cache these Pages by Default |
| 16 | +------------------------------------------------- |
| 17 | + |
| 18 | +There are many ways to generate unique tokens for each user but in order get |
| 19 | +them validated when the form is submitted, you need to store them inside the |
| 20 | +PHP Session. |
| 21 | + |
| 22 | +If you are using Varnish or some similar reverse proxy cache and you try to cache |
| 23 | +pages containing forms with CSRF token protection, you will see that, by default, |
| 24 | +Varnish fails to cache them. |
| 25 | + |
| 26 | +This happens because a cookie is sent in order to preserve the PHP session open and |
| 27 | +Varnish default behaviour is to not cache HTTP requests with cookies. |
| 28 | + |
| 29 | +If you think about it, if you managed to cache the form you would end up |
| 30 | +with many users getting the same token in the form generation. When these |
| 31 | +users try to send the form to the server, the CSRF validation will fail for |
| 32 | +them because the expected token is stored in their session and different |
| 33 | +for each user. |
| 34 | + |
| 35 | +How to Cache most of the Page and still Be Able to Use CSRF Protection |
| 36 | +---------------------------------------------------------------------- |
| 37 | + |
| 38 | +To cache a page that contains a CSRF token you can use more advanced caching |
| 39 | +techniques like `ESI`_ fragments, having a TTL for the full page and embedding |
| 40 | +the form inside an ESI tag with no cache at all. |
| 41 | + |
| 42 | +Another option to be able to cache that heavy page would be loading the form |
| 43 | +via an uncached AJAX request but cache the rest of the HTML response. |
| 44 | + |
| 45 | +Or you can even load just the CSRF token with an AJAX request and replace the |
| 46 | +form field value with it. |
| 47 | + |
| 48 | +.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery |
| 49 | +.. _`ESI`: http://www.w3.org/TR/esi-lang |
| 50 | +.. _`Security CSRF Component`: https://github.com/symfony/security-csrf |
0 commit comments