首页 > 解决方案 > Django:没有在 iframe 中设置 CSRF Coo​​kie——没有 csrf 豁免的解决方法

问题描述

我的项目正在几个 3rd 方站点上部署 iframe,这些站点都是已知的并在 django 应用程序中注册。

在这些 iframe 中,用户可以触发一些 ajax 形式的事件。直接打开网站,一切正常。如果我打开包含 iframe 的第 3 方站点,django 在触发 ajax 事件(403)后会抛出错误,说 CSRF 失败。

在表单中,我使用了在 html 中设置的 {% csrf_token %}。但是,当通过 iframe 调用站点时,它没有设置相应的 cookie(在浏览器中都使用检查模式发现)。

我确实知道我可以使用装饰器@csrf_exempt,但这会同时禁用 csrf-protection,我不想这样做。

所以我的问题是:

  1. 当整个页面通过 iframe 加载时,为什么 django 不设置 CSRF Coo​​kie?
  2. 是否可以让 django 设置 cookie 或者是否可以只从 csrf 中排除已知的 url?
  3. 有没有我看不到的方法?

非常感谢您的时间!:)

标签: djangoiframecsrf

解决方案


我正在处理同样的问题,Midas Gossye 的回答对我不起作用。settings.py我的解决方案是在站点位于 iframe 中时进行以下编辑以让 Django 设置 CSRF cookie。

  1. 设置CSRF_COOKIE_SAMESITE = None,因为您希望将 CSRF cookie 从您的站点发送到在 iframe 中包含它的站点(
  2. 确保 Django 将 CSRF cookie 标记为安全的,使用CSRF_COOKIE_SECURE = True. 这意味着浏览器将确保此 cookie 仅通过 HTTPS 发送(来源)。您应该拥有它,因为它更安全,并且未来版本的浏览器只会发送带有 SameSite=None 的 cookie,前提是它也被标记为安全。
  3. 您不需要CSRF_TRUSTED_ORIGINS像以前的答案之一那样设置,事实上,出于安全原因,您不应该这样做。这是因为如果用户通过 iframe 使用您的站点,则 POST 请求仍然来自您的站点,而不是来自其他服务器。仅当 POST 请求来自另一台服务器上的站点时才需要此设置(来源

您可能需要清除 Django 站点上的 cookie(应该包括 csrftoken cookie),然后重新加载并检查新的 csrftoken 是否标记为“安全”并且没有“SameSite”。

现在,当第 3 方页面在 iframe 中有您的页面时,应该设置 csrftoken cookie(您可以通过让您的页面使用 Javascript 打印csrftokencookie 来确认),并且您应该能够从 iframe-d 发出成功的 POST 请求Django 网站。


推荐阅读