如何在 django 的预检 CORS POST 请求中处理 CSRF?
Posted
技术标签:
【中文标题】如何在 django 的预检 CORS POST 请求中处理 CSRF?【英文标题】:How to handle CSRF in preflighted CORS POST request in django? 【发布时间】:2013-11-25 18:23:43 【问题描述】:我正在尝试通过 AJAX 从abc.com
向xyz.com
(这是一个 Django 应用程序)的 URL 发出 POST
请求。
我通过向xyz.com
上的URL 发出GET
请求来获取CSRF 令牌,但是当在预检请求中向xyz.com
发出OPTIONS
请求时,令牌会发生变化。
有没有办法在预检请求中得到OPTIONS
请求的响应?
注意:
我正在遵循以下来源的说明:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS http://www.html5rocks.com/en/tutorials/cors/【问题讨论】:
CSRF 中间件旨在阻止您想要做的事情。您需要保存 cookie 并随您提出的每个请求一起发送。或者基本上你可以禁用中间件。顺便说一句,现代浏览器不会接受跨域请求,除非你有 crossdomain.xml 允许其他方发出请求。 @scriptmonster 我不想禁用 CSRF,我想要一种方法来获取明确验证的来源的 CSRF 令牌。 @scriptmonster 你对跨源通信很困惑。 Crossdomain.xml 仅适用于 flash 和 java applet。我建议你在developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS阅读CORS。 @vedarthk 您无权访问服务器对预检的响应。 我之前的评论有误。我再次查看了spec 并且cookie 没有通过OPTIONS 预检传递,即使withCredentials="true" 也是如此。考虑在 Django 站点上使用 github.com/ottoyiu/django-cors-headers 中间件。 【参考方案1】:查看django-cors-headers
,您可能会发现它更适合解决您的问题:
https://github.com/ottoyiu/django-cors-headers/
Django-rest-framework recommends http://www.django-rest-framework.org/topics/ajax-csrf-cors
【讨论】:
我自己编写了与django-cors-headers
相同的中间件(我不知道)。【参考方案2】:
Django CSRF 保护将允许 OPTIONS 请求,所以第一阶段没有问题:
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-it-works
如果我理解正确,那么您希望允许下一个请求(例如跨域 POST)通过。为了让它工作并通过 Django 的 CSRF 保护,请求必须发送一个 CSRF 令牌(在 POST 数据中或在 AJAX 的标头中)和一个匹配的 CSRF cookie。
现在,跨域限制使 abc.com 无法为 xyz.com 设置或读取 cookie,无论是来自 javascript 还是来自服务器端响应。因此,这种方法是不可能的。
相反,您必须将@csrf_exempt
应用于视图。这将允许任何网站发布到它。因此,您需要为视图构建一些其他保护。当然,您需要自行检查保护的安全性。请记住,'Referer' 和 'Origin' 标头可以很容易地用 curl 等基本的东西伪造。
【讨论】:
我知道OPTIONS
请求由 Django 提供,但在该请求中,CSRF 令牌被重新生成,我无法在预发送请求中捕获它。这种方法并非不可能,我可以通过稍微修改中间件来验证 CSRF 令牌而不禁用 CSRF 保护来做到这一点。以上是关于如何在 django 的预检 CORS POST 请求中处理 CSRF?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Django 和 Angular 的 CORS 预检请求
django-cors-headers 和 nginx 配置:预检响应缺少 CORS 标头
Angular CORS 简单请求在 POST 中触发带有 Authorization 标头的预检