admin管理员组文章数量:1355123
We're in the process of moving our frontend into a separate project (out of Django). It's a Javascript single page application.
One of the reasons is to make it easier for our frontend developers to do their work, not having to run the entire project -- including the API -- locally. Instead, we'd like them to be able to municate with a test API we've set up.
We've managed to solve most of the CORS/CSRF issues along the way. But now we've run into something I can't find a solution for anywhere, despite reading lots of documentation and SO answers.
The frontend and the API are served from different domains (during development localhost
and test-api.example
). Until now, while served from the same domain, the frontend has been able to get the CSRF token from the csrftoken
cookie set by the API (Django). But when served from different domains, the frontend (localhost
) can't access the cookies of the API (api-test.example
).
I'm trying to figure out a way to work around this, to somehow deliver the CSRF token to the frontend. The Django docs remend to set a custom X-CSRFToken
header for AJAX requests. Would we promise the CSRF protection if we similarly served the CSRF token in every response as header and (via Access-Control-Expose-Headers
) allowed this header to be read by the frontend?
Given that we've set up CORS properly for the API (i.e. only allowing certain domains to do cross origin requests to the API), JS on 3rd party sites should not be able to read this response header, thus not be able to make promising AJAX requests behind the back of our users, right? Or did I miss something important here?
Or is there another, better way to achieve what we want?
We're in the process of moving our frontend into a separate project (out of Django). It's a Javascript single page application.
One of the reasons is to make it easier for our frontend developers to do their work, not having to run the entire project -- including the API -- locally. Instead, we'd like them to be able to municate with a test API we've set up.
We've managed to solve most of the CORS/CSRF issues along the way. But now we've run into something I can't find a solution for anywhere, despite reading lots of documentation and SO answers.
The frontend and the API are served from different domains (during development localhost
and test-api.example.
). Until now, while served from the same domain, the frontend has been able to get the CSRF token from the csrftoken
cookie set by the API (Django). But when served from different domains, the frontend (localhost
) can't access the cookies of the API (api-test.example.
).
I'm trying to figure out a way to work around this, to somehow deliver the CSRF token to the frontend. The Django docs remend to set a custom X-CSRFToken
header for AJAX requests. Would we promise the CSRF protection if we similarly served the CSRF token in every response as header and (via Access-Control-Expose-Headers
) allowed this header to be read by the frontend?
Given that we've set up CORS properly for the API (i.e. only allowing certain domains to do cross origin requests to the API), JS on 3rd party sites should not be able to read this response header, thus not be able to make promising AJAX requests behind the back of our users, right? Or did I miss something important here?
Or is there another, better way to achieve what we want?
Share Improve this question asked Mar 12, 2018 at 16:28 decibytedecibyte 80112 silver badges18 bronze badges2 Answers
Reset to default 4I didn't understand your question at first, so allow me to summarize: you can't get the CSRF token from the cookie on the client because the Same Origin Policy blocks you from accessing cross-domain cookies (even with CORS). So you're suggesting that the server transmit the cookie to the client in a custom header instead, and are wondering if that's secure.
Now, the documentation does make a suggestion for how to transmit the token if you're not using the cookie: put it in the response body. For example, you could use a custom meta
tag. When it es to security I lean towards using remended solutions rather than trusting my own analysis of something new.
That caveat aside, I don't see any security problem with what you're suggesting. The Same Origin Policy will prevent a third-party site from reading the headers just as it will the body, and you can opt in to reading them from your client domain with the CORS Access-Control-Expose-Headers
header.
You might find this answer interesting, as it lays out the advantages and disadvantages of various CSRF token schemes. It includes the use of a custom response header, and—to the point of your question—confirms: "If a malicious user tries to read the user's CSRF token in any of the above methods then this will be prevented by the Same Origin Policy".
(You might want to look into whether you need Django's CSRF protection at all with your SPA. See this analysis, for example. That's outside the scope of this question, though.)
Assume you already have corsheaders
installed. Write a Django middleware and include it in your MIDDLEWARE settings:
from django.utils.deprecation import MiddlewareMixin
class CsrfHeaderMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if "CSRF_COOKIE" in request.META:
# csrfviewmiddleware sets response cookie as request.META['CSRF_COOKIE']
response["X-CSRFTOKEN"] = request.META['CSRF_COOKIE']
return response
expose the header in your settings:
CORS_EXPOSE_HEADERS = ["X-CSRFTOKEN"]
When you make a GET
API call from you JS, you should get X-CSRFTOKEN
from response header, go ahead and include it in the request header when you make POST
PUT
PATCH
DELETE
requests.
本文标签: javascriptCSRF and CORS with Django (REST Framework)Stack Overflow
版权声明:本文标题:javascript - CSRF and CORS with Django (REST Framework) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743946334a2566474.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论