打开新的浏览器选项卡会使 Django 的 CSRF 令牌无效,从而阻止表单提交

Posted

技术标签:

【中文标题】打开新的浏览器选项卡会使 Django 的 CSRF 令牌无效,从而阻止表单提交【英文标题】:Opening a new browser tab invalidates Django's CSRF token, preventing form submission 【发布时间】:2017-09-03 21:40:34 【问题描述】:

在第二个浏览器选项卡中打开 Django 1.10 应用程序会刷新 CSRF 令牌。这会破坏第一个选项卡中的所有表单 - 即,以前打开的表单无法再提交,因为旧的 CSRF 令牌现在无效。

如何避免这种行为?

分步示例:

    用户正在选项卡 A 中查看表单。 用户在选项卡 B 中打开应用程序。 用户返回选项卡 A 并尝试提交表单。 错误:禁止 (403)。 CSRF 验证失败。请求中止。

一些细节:

我真的很想在应用程序中允许多标签浏览。

Django 1.10 release notes 记录了对 CSRF 机制的更改:

为了防止 BREACH 攻击,现在的 CSRF 保护机制 在每个请求上更改表单令牌值(同时保持 可用于验证不同令牌的不变秘密)。

Django 的1.9 CSRF documentation 对可用性问题的描述非常好。这一段已经在1.10 CSRF documentation 中删除了,但它似乎描述了我遇到的确切问题:

为什么不为每个请求使用一个新令牌?

从 UI 为每个请求生成一个新令牌是有问题的 透视,因为它使所有以前的形式无效。大多数用户 如果发现在您的网站上打开新标签页会非常不高兴 使他们刚刚花时间填写的表格无效 选项卡或他们通过后退按钮访问的表单无法 填写完毕。

【问题讨论】:

这真的很有趣。由于没有记录如何绕过这种行为,我建议你在 Django 的 IRC 频道上提问。你会在那里找到一些 Django 核心开发人员,他们可能会回答。 谢谢@xyres,我试试看。 【参考方案1】:

如果您在视图中使用 @csrf_protect 装饰器,请尝试使用 @csrf_exempt 装饰器。

views.py之前:

    from django.views.decorators.csrf import csrf_protect

    @csrf_protect
    def view(request):
         # Render Something

views.py之后:

    from django.views.decorators.csrf import csrf_exempt

    @csrf_exempt
    def view(request):
         # Render Something

抱歉回复晚了。 迟到总比没有好。

【讨论】:

这不是一个好主意。它会禁用视图的 csrf 保护。

以上是关于打开新的浏览器选项卡会使 Django 的 CSRF 令牌无效,从而阻止表单提交的主要内容,如果未能解决你的问题,请参考以下文章

在 Chrome 中几秒钟后选项卡会变回第一个选项卡

为啥单击按钮后`JQuery`选项卡会丢失样式

如果存在很多选项卡,导航选项卡会使用省略号调整宽度

在内部选项卡之前加载的选项卡会导致错误“提供给选项卡组件的值无效”

无法创建新的证书签名请求 (CSR)?

更改基于选项卡的应用程序上的选项卡会向下推 UI 元素