django csrf 令牌在每个请求上都必须是唯一的吗?

Posted

技术标签:

【中文标题】django csrf 令牌在每个请求上都必须是唯一的吗?【英文标题】:Does django csrf token must be unique on every request? 【发布时间】:2014-10-19 21:05:29 【问题描述】:

我有一个关于 Django CsrfViewMiddleware 机制的问题。 我知道,那个 Django:

    为每个请求设置新的 csrftoken cookie。 检查,X-CSRFToken 标头值(或隐藏输入“csrfmiddlewaretoken”)必须等于 csrftoken cookie。

但 Django 不会检查令牌是否已经被使用(来自 CsrfViewMiddleware 的示例):

if not constant_time_compare(request_csrf_token, csrf_token):
            return self._reject(request, REASON_BAD_TOKEN)

所以我可以使用相同的令牌发布多个请求(我在我的服务器上进行了测试)。

这是标准行为,还是我的 Django 设置不正确? 谢谢。

【问题讨论】:

标准。令牌不会被消耗,而只会在每次登录时刷新。 知道了。 Germano,谢谢你的回答! 【参考方案1】:

不消耗 CSRF 令牌。

详细说明 Germano 的评论,背后的原因很简单:

多个浏览器窗口/选项卡REST

本质上,Django 必须为过去呈现的每个页面创建(并持久化,并在分布式“云”部署中同步)新的 CSRF 令牌。从本质上讲,这很容易导致拒绝服务攻击,在这种攻击中,您无法假设 CSRF 有任何合理的到期时间。

【讨论】:

所以解决办法是自己写一个中间件,里面会检查CSRF token的过期时间? 不完全——你基本上不想为不同的视图或页面存储许多不同的 CSRF——否则,你创建了一种机制,你可以很容易地用大量​​的 CSRF 使数据库过载。 我不明白这个问题。为什么要让令牌提前过期? 目的是禁用两次post html表单。我在页面上有 javascript 检查,但我也想在服务器上添加检查。 @Germano,没有。例如,在网上商店用户下订单。当他单击“下订单”按钮时,POST 请求被发送到服务器。如果用户单击两次,将向服务器发送两个 POST 请求。我想防止这种情况发生。

以上是关于django csrf 令牌在每个请求上都必须是唯一的吗?的主要内容,如果未能解决你的问题,请参考以下文章

Django 手动检查 CSRF 令牌

跨站请求伪造 (CSRF) 缓解

如何以及在何处生成 CSRF 令牌以通​​过 REST API 向 Django 应用程序发出请求?

如何使用 Django 和 AngularJS 创建 POST 请求(包括 CSRF 令牌)

如何将 Django 的 CSRF 令牌添加到 jQuery POST 请求的标头?

Pyres 工作人员对我的视图的 Django POST 请求 - CSRF 令牌