【问题标题】:Django: CSRF Cookie not set in iframe -- workaround without csrf exemptDjango:没有在 iframe 中设置 CSRF Coo​​kie——没有 csrf 豁免的解决方法
【发布时间】:2019-05-06 08:45:29
【问题描述】:

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

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

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

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

所以我的问题是:

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

非常感谢您的宝贵时间! :)

【问题讨论】:

  • 我不知道,但是 CSRF 意味着跨站点请求伪造,并且在第三方服务器上的 iframe 中部署站点是一种跨站点,对吗?它不起作用的事实意味着它实际上按预期工作。

标签: django iframe csrf


【解决方案1】:

这是我在 settings.py 文件中更改的内容,以使类似的工作:

X_FRAME_OPTIONS = 'ALLOW-FROM example.com'
CSRF_TRUSTED_ORIGINS = ['example.com']
CSRF_COOKIE_SAMESITE = None

example.com 是您插入 iframe 的域。 最后一个选项是最近才在 Django 中引入的,因此根据您的版本,它可能不是必需的。

【讨论】:

【解决方案2】:

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

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

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

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

【讨论】:

猜你喜欢
  • 2018-12-30
  • 2013-07-16
  • 1970-01-01
  • 2016-04-19
  • 2020-06-22
  • 2020-11-02
  • 2016-03-16
  • 2021-07-20
相关资源
最近更新 更多