问题
My project is deploying iframes on several 3rd party sites, that are all known and registered within the django application.
In these iframes, users can trigger some ajax-form events. Opening the site directly, everything works fine. If I open the 3rd party site, containing the iframe, django is throwing an error after firing the ajax event (403), saying that CSRF failed.
In the form I used {% csrf_token %} which is set in the html. However it does not set the corresponding cookie, when calling the site through the iframe (found out both using inspection mode in browser).
I do know that I could use a decorator @csrf_exempt
, but that will disable csrf-protection all in one, which I don´t want to do.
So my questions are:
- Why does django not set the CSRF Cookie, when the whole page is loaded through an iframe?
- Is it possible to get django to set the cookie OR is it possible to only exempt the known urls from csrf?
- Is there a way I dont see?
Thanks a lot for your time! :)
回答1:
This is what I changed in my settings.py file to get something similar working:
X_FRAME_OPTIONS = 'ALLOW-FROM example.com'
CSRF_TRUSTED_ORIGINS = ['example.com']
CSRF_COOKIE_SAMESITE = None
Where example.com is the domain that you insert the iframe into. The last option was only introduced quite recently in Django, so depending on your version it might not be necessary.
回答2:
I was dealing with the same issue, and the answer by Midas Gossye didn't work for me. My solution was to make the following edits in settings.py
to get Django to set the CSRF cookie, when the site is in an iframe.
- Set
CSRF_COOKIE_SAMESITE = None
, because you want the CSRF cookie to be sent from your site to the site that has it in an iframe (source) - Make sure Django marks the CSRF cookie as secure, with
CSRF_COOKIE_SECURE = True
. This means that browsers will make sure this cookie is sent over HTTPS only (source). You should have this because it's more secure, and future versions of browsers will only send cookies with a SameSite=None if it is also marked as Secure. - You don't need to set the
CSRF_TRUSTED_ORIGINS
like one of the previous answers suggests, in fact arguably you shouldn't because of security reasons. This is because if a user is using your site through an iframe, the POST requests are still coming from your site, not from some other server. This setting is only needed if POST requests will come from a site on another server (source)
You will probably have to clear the cookies that you had on your Django site (should include the csrftoken cookie), and reload and check that the new csrftoken is marked as "Secure" and doesn't have a "SameSite".
Now, the csrftoken cookie should be set when a 3rd party page has your page in an iframe (you can confirm by having your page use Javascript to print the csrftoken
cookie), and you should be able to make successful POST requests from your iframe-d Django site.
来源:https://stackoverflow.com/questions/53621161/django-csrf-cookie-not-set-in-iframe-workaround-without-csrf-exempt