Django:未在iframe中设置CSRF Coo​​kie-无需csrf豁免的解决方法

时间:2018-12-04 20:46:55

标签: django iframe csrf

我的项目是在django应用程序中已知并注册的多个第三方站点上部署iframe。

在这些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. 有没有我看不见的方式?

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

2 个答案:

答案 0 :(得分:2)

这是我在settings.py文件中所做的更改,以实现类似的工作:

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

example.com 是将iframe插入其中的域。 最后一个选项是Django才刚刚引入的,因此根据您的版本,可能没有必要。

答案 1 :(得分:0)

我正在处理相同的问题,并且在站点settings.py中进行了以下编辑,以使Django在站点位于iframe中时设置CSRF cookie。

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

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

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