仅在 Opera 上的 ajax 发布请求上的 Django CSRF 失败

Posted

技术标签:

【中文标题】仅在 Opera 上的 ajax 发布请求上的 Django CSRF 失败【英文标题】:Django CSRF failure on ajax post requests on Opera only 【发布时间】:2011-09-21 00:42:48 【问题描述】:

好的,所以 AJAX POST 请求在 Mozilla 和 Chromium 中工作正常,但在 Opera 中失败。我得到标准的 CSRF 错误 (403)。我尝试了不同版本的 Opera,但我尝试的每一个都失败了。顺便说一句,我正在使用在标头中设置 X-CSRFToken 的 jquery/django sn-p,正如下面的“坏 Opera 请求”中所验证的那样。

我在另一个非常简单的项目中创建了一个视图,并且 ajax 发布请求在 Opera 中运行良好。我查看了请求详细信息并看到了差异。好的请求并没有设置任何奇怪的 X-Opera-Info 和其他歌剧参数,即使我认为我使用的是同一个浏览器。如果这是问题,有没有办法删除那些额外的参数?或者是否有人对问题可能有任何其他建议或想法?我知道这不是我的视图函数,因为我尝试立即返回一个 HttpResponse,甚至得到 403'd。谢谢百万人。

####################
OPERA GOOD REQUEST
##############
Request details
POST /test HTTP/1.1 
User-Agent: Opera/9.80 (X11; Linux i686; U; en) Presto/2.7.62 Version/11.00
Host: 127.0.0.1:8000
Accept-Language: en-US,en;q=0.9
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Referer: http://127.0.0.1:8000/test
Cookie: csrftoken=1c6441404c991f7ae3b6d7d49f91f280
Cookie2: $Version=1
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
Content-Length: 6
Content-Type: application/x-www-form-urlencoded
Accept: */*
X-CSRFToken: 1c6441404c991f7ae3b6d7d49f91f280
X-Requested-With: XMLHttpRequest
Content-Transfer-Encoding: binary

###################
OPERA BAD REQUEST
####################
Request details
POST http://facebook.example.com/remove-person HTTP/1.1 
User-Agent: Opera/9.80 (X11; Linux i686; U; en) Presto/2.7.62 Version/11.00
Host: facebook.example.com
Accept-Language: en-US,en;q=0.9
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Referer: http://facebook.example.com/
Cookie: signed_request=5-f0_7pZLILrp6MLocsdMoNYAaZr-wCnU2cPbLC1bZg.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg4MTYwMDAsImlzc3VlZF9hdCI6MTMwODgxMTQyNywib2F1dGhfdG9rZW4iOiIyMjMyNDY5NDEwMjc3MTR8Mi5BUURVRGM2ZFFLSElnN1h3LjM2MDAuMTMwODgxNjAwMC4xLTU0MDIwMjZ8b2QtX1diNTh3aG1wTnNHYUh4cTNtOVBpWkswIiwidXNlciI6eyJjb3VudHJ5IjoidXMiLCJsb2NhbGUiOiJlbl9VUyIsImFnZSI6eyJtaW4iOjIxfX0sInVzZXJfaWQiOiI1NDAyMDI2In0; csrftoken=d4cdc6a75ed264d295a410dd98982c42; fbs_223246941027714="access_token=223246941027714%7C2.AQBlhzavZjzd8c7J.3600.1308819600.1-5402026%7CdsD6VESpGJb3m0EdD1mhFZtDI24&base_domain=example.com&expires=1308819600&secret=QaTNS988wl0FU6A0LG9qDQ__&session_key=2.AQBlhzavZjzd8c7J.3600.1308819600.1-5402026&sig=61e7e13091501f35793d3cda8c20835b&uid=5402026"
Cookie2: $Version=1
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
Content-Length: 14
X-Opera-Info: ID=448, p=4, f=15, sw=1440, sh=900
X-Opera-ID: e79c37b56a58510d26b56882453bddb6d2c2dae858129139113f6346ea23ca6b
X-Opera-Host: r18-02:12420
X-OA: 1322 b5834cb13259fbd50b87b576b5e8b9a8bcc1384478c2ea79cc65614dc1b67c27
X-OB: evenes
Content-Type: application/x-www-form-urlencoded
Accept: */*
X-CSRFToken: d4cdc6a75ed264d295a410dd98982c42
X-Requested-With: XMLHttpRequest
Content-Transfer-Encoding: binary

【问题讨论】:

【参考方案1】:

我最近遇到了类似的问题。我第一次尝试从 AJAX 发布关于 Django 没有发送 CSRF cookie 的视图。由于我无法解释的原因,这适用于我尝试过的所有浏览器,除了 Opera。

这个场景是described in the Django docs,他们建议使用ensure_csrf_cookie装饰器。

如果使用该装饰器包装所有潜在视图过于繁琐,您可以做的另一件事是在基本模板中添加类似这样的内容:

<script>
var csrf_token = " csrf_token ";
</script>

然后,每当您进行 AJAX 发布时,请始终将密钥对 csrfmiddlewaretoken: csrf_token 包含在您的 POST 数据中。

完成上述操作后,我在 Opera 上的帖子就开始工作了。

【讨论】:

【参考方案2】:

如果您禁用 Opera Turbo,它会起作用吗?这些额外的标头似乎与 Turbo 相关,也许这会有所不同。

【讨论】:

【参考方案3】:
X-CSRFToken:  csrf_token 

值应该在 AJAX 请求 HTTP 标头中从客户端发送以被 Django 识别

【讨论】:

以上是关于仅在 Opera 上的 ajax 发布请求上的 Django CSRF 失败的主要内容,如果未能解决你的问题,请参考以下文章

原生的ajax请求----(播放托管到爱奇艺上的视频)

Ajax CORS 替代品

Kestrel 上的 Blazor Windows 身份验证仅在本地工作?在身份验证握手请求之间收到匿名请求

跨域 Ajax 请求在 Opera 和 IE9 中不起作用?

多个页面上的多个 ajax 和表单发布请求

ssl上的phonegap ajax请求错误