Laravel Litespeed Cache package contains ESI support
Full page caching poses a problem when using user specific content like csrf tokens. joostvanveen/laravel-litespeedcache now enables a easy solution using ESI blocks.
CSRF tokens in Laravel
Laravel has built in security to guard against csrf attacks, using a csrf token. A token check is done on every POST request.
Typically, you provide the csrf token as a hidden field in a form, using `csrf_field()` or in a POST ajax request, using something like $.post(route('my.route'), $('#form').serialize() + "&_token={{ csrf_token() }});
The problem with csrf tokens and full page cache
This poses a problem when used with a full page cache like Litespeed Cache or Varnish. The csrf is unique and should not be stored in cache. If it is you will be posting a cached csrf token instead of a fresh one, resulting in a 'This page has expired' error on doing a POST request. However, you do want to store the rest of the page in cache. You need some way to do hole punching in your cached page. ESI to the rescue.
The solution for csrf tokens and full page cache
The joostvanveen/laravel-lightspeedcache package provides two ways to use csrf tokens in you pages as an ESI block. On constructing the cached page, the ESI block will be replaced by the actual, uncached csrf token. This way you can have a fully cached paged, but with a uncached token.
Use the following code to include a hidden field in a form on a cached page, instead of csrf_field()
. The litespeedcache.routes.field
route is part of this package an will return a hidden field with csrf token. Use the ESI block in your page like so:
<esi:include src="{{ route('litespeedcache.csrf.field') }}" />
If your Litespeed server does not support ESI then you can always load the csrf token via ajax and add the ajax URL to your list of URIs that should not be cached.