Caching static pages without CSRF token
Hi,
I'm looking to use expires_in
method in my actions who returns static content.
For this pages I would like to return a cache control header where public
is true
. Like this it allow an proxy cache to store the content.
My question is more about CSRF token meta tags. I'm looking to have the CSRF meta tags not printed out when I use cache control has public. I was first looking to play with protect_from_forgery
options but still print the tags.
I finally saw into Rails code that csrf_meta_tags
are only printed if protect_against_forgery?
returns true
. And that is linked to self.allow_forgery_protection
.
So I do this code that works for me.
class ApplicationController < ActionController::Base
...
def expires_in(seconds, options = {})
super
self.allow_forgery_protection = false if options.fetch(:public, false)
end
end
But may be there is a better way to do it or may be I miss some Rails tools.
What do you think about?
CSRF tokens are generated for each user, which is why they should not be cached. The CSRF tokens are specific to each user and request so that you can determine whether or not it was the user taking this action or malicious code.
To solve this you have 3 options:
- Don't cache the form
- If you're fragment caching, use Javascript to include the CSRF token. See here: https://coderwall.com/p/0sctaa/forms-csrf-authenticity-token-and-fragment-caching-in-rails
- If you're doing full-page caching, use one of these mthods: https://www.fastly.com/blog/caching-uncacheable-csrf-security
Hi Chris,
Thanks for your answer and sorry for the time I spent to send mine.
In my case I'm looking for caching a full-page. My website doesn't contain form for now. It's only static pages. It will have a blog and may be a contact page with a form in the futur.
It's why I was looking to have an cache control as public for main of the pages. I looked https://www.fastly.com/blog/caching-uncacheable-csrf-security, but I plan to use nginx to cache pages. So I can't use ESI. I could use cookie or an endpoint.
But may be in my case, I could just no care about meta tags and cache them anyway. Until I don't use cache control public
in page with form.
Hey Nicolas,
That's great then. If you don't have any forms or anything for now, just cache it all and don't care about it.
You can add Javascript and an endpoint for the CSRF token later on when you add the contact form in the footer which you'll probably want to submit with AJAX anyways. It'd make perfect sense to just add in a csrf endpoint to retrieve the token and submit it in that case.
That's one of the easier solutions for caching since you don't have too much dynamic content and that'll make your life a whole lot simpler. :)