Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Last revision Both sides next revision
litespeed_wiki:cache:laravel_esi [2019/04/10 11:59]
Lucas Rolff created
litespeed_wiki:cache:laravel_esi [2019/05/02 08:45]
Lucas Rolff Add CSRF info for OLS
Line 1: Line 1:
-=====Use LSCache with CSRF Tokens in Laravel=====+======Use LSCache with CSRF Tokens in Laravel=====
 + 
 +**This wiki assumes you're using our [[https://​github.com/​litespeedtech/​lscache-laravel|Laravel LSCache]] composer package.**
  
 When you're building a web application that contains forms, it's quite common that you have CSRF tokens to prevent cross-site scripting (XSS). However, if you want to use LSCache within your application,​ this often breaks form submissions because everyone gets the same CSRF token, unless you've set private cache as the default when enabling LSCache. When you're building a web application that contains forms, it's quite common that you have CSRF tokens to prevent cross-site scripting (XSS). However, if you want to use LSCache within your application,​ this often breaks form submissions because everyone gets the same CSRF token, unless you've set private cache as the default when enabling LSCache.
Line 11: Line 13:
   Route::​get('/​csrf',​ function() {   Route::​get('/​csrf',​ function() {
       $response = csrf_token();​       $response = csrf_token();​
-      return response($response,​ 200)->header('X-LiteSpeed-Cache-Control',​ 'private,max-age=900'​); +      return response($response,​ 200); 
-  });+  })->middleware('lscache:private;max-age=900'​);​
  
 What we are doing here is solely generating a CSRF token. We make it private in such a way that the response becomes unique to the user, and we cache it for 900 seconds (15 minutes). Since the tokens do not constantly refresh, there is no need to do an ESI call for every pageview if we can avoid it. What we are doing here is solely generating a CSRF token. We make it private in such a way that the response becomes unique to the user, and we cache it for 900 seconds (15 minutes). Since the tokens do not constantly refresh, there is no need to do an ESI call for every pageview if we can avoid it.
Line 18: Line 20:
 The default session timeout in Laravel is 120 minutes (2 hours). By setting a lower max-age on the cache-control for CSRF, we make sure that the ''/​csrf''​ endpoint gets called every 15 minutes (if the visitor has activity), this will keep the session "​alive"​ and continue to extend the lifetime of the session by 120 minutes after "last activity"​. The default session timeout in Laravel is 120 minutes (2 hours). By setting a lower max-age on the cache-control for CSRF, we make sure that the ''/​csrf''​ endpoint gets called every 15 minutes (if the visitor has activity), this will keep the session "​alive"​ and continue to extend the lifetime of the session by 120 minutes after "last activity"​.
  
-===CSRF Tokens in Forms===+=====CSRF Tokens in Forms=====
  
 Next, we add an ''​ESI_ENABLED=true''​ to our .env file, since we'll use this in our views where we need the CSRF token. Next, we add an ''​ESI_ENABLED=true''​ to our .env file, since we'll use this in our views where we need the CSRF token.
Line 42: Line 44:
 What we do is to check whether ''​ESI_ENABLED''​ is ''​true''​. If it is, we generate our token using the esi:include call. If ''​ESI_ENABLED''​ is set to ''​false'',​ we use the Laravel helper @csrf to generate the CSRF token. What we do is to check whether ''​ESI_ENABLED''​ is ''​true''​. If it is, we generate our token using the esi:include call. If ''​ESI_ENABLED''​ is set to ''​false'',​ we use the Laravel helper @csrf to generate the CSRF token.
  
-===CSRF Meta Tag Token===+=====CSRF Meta Tag Token=====
  
 Laravel also stores your CSRF token in a meta tag. This is used for JavaScript-driven applications,​ so we want to make sure the token is available in a meta tag as well. Laravel also stores your CSRF token in a meta tag. This is used for JavaScript-driven applications,​ so we want to make sure the token is available in a meta tag as well.
Line 60: Line 62:
 We once again simply use our ''​ESI_ENABLED''​ environment variable to handle the decision whether to use ESI or not. We once again simply use our ''​ESI_ENABLED''​ environment variable to handle the decision whether to use ESI or not.
  
-===CSRF in window.Laravel Implementation===+=====CSRF in window.Laravel Implementation=====
  
 Older Laravel applications can also have their CSRF token set in a ''​window.Laravel''​ variable in JavaScript. This method isn't used anymore, but in case you have an older Laravel application,​ you can also handle this by doing: Older Laravel applications can also have their CSRF token set in a ''​window.Laravel''​ variable in JavaScript. This method isn't used anymore, but in case you have an older Laravel application,​ you can also handle this by doing:
Line 72: Line 74:
   </​script>​   </​script>​
  
-==Remember to enable ​ESI==+=====Remember to Enable ​ESI=====
  
-In your .htaccess file, you can enable ESI for all requests:+We have a small example here of how to enable ​the ESI engine:
  
-  ​<​IfModule LiteSpeed>​ +  ​Route::​get('/​csrf',​ function() { 
-  ​RewriteEngine on +      ​$response = csrf_token();​ 
-  ​RewriteRule .? [E=esi_on:1,E=cache-control:​max-age=3600+      return response($response,​ 200); 
-  CacheLookup ​on +  ​})->​middleware('​lscache:​private;​max-age=900'​);​ 
-  ​</​IfModule>​+   
 +  Route::​get('/​contact'​function() { 
 +      return view('​contact'​);​ 
 +  })->​middleware('​lscache:​max-age=3600;​public;​esi=on'); 
 +  ​ 
 +We use our ''​lscache''​ middleware to set a max age of 1 hour, set the cacheability to public and enable the ESI engine with ''​esi=on''​. It's important that you use ''​esi=on''​ within the lscache-middleware for all the pages where you use your ESI blocks - if you do not add this, the ESI engine won't get enabled and ESI won't be used.
  
-Howeverwe do advise that you enable ESI using the ''​X-LiteSpeed-Cache-Control'' ​response headerIt also allows you to do more fine-grained control over how long you want to cache the pageswhether it should be private or public cacheetc.+For performance reasonsplease ​do not enable ESI globally. 
 + 
 +=====How to handle CSRF if you'​re ​using OpenLiteSpeed===== 
 + 
 +OpenLiteSpeed doesn'​t have ESI available, so you can't use the above ESI implementation with OpenLiteSpeed,​ however, we can still do something similar using javascript:​ 
 + 
 +  <script type="​text/​javascript">​ 
 +    $(document).ready(function () { 
 +      $.ajax({ 
 +        url: '/csrf'
 +        success: function(csrf_token) { 
 +          $('​meta[name=csrf-token]').attr('content',​ csrf_token);​ 
 +          $('​input[name=_token]'​).attr('​value',​ csrf_token);​ 
 +        } 
 +      }); 
 +    }); 
 +  </​script>​ 
 + 
 +You'll still use the ''/​csrf''​ endpoint mentioned earlier: 
 + 
 +  Route::​get('/​csrf'​function() { 
 +      $response = csrf_token();​ 
 +      return response($response200); 
 +  })->​middleware('​lscache:​private;​max-age=900'​);​
  • Admin
  • Last modified: 2020/08/29 14:29
  • by Lisa Clarke