“CSRF 令牌丢失或不正确”而在 Django 中通过 AJAX 发布参数
我尝试发布类似的参数
jQuery.ajax(
{
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': "{content:'xxx'}",
'dataType': 'json',
'success': rateReviewResult
}
);
,但是,Django 返回 Forbidden 403. CSRF 验证失败。请求已中止。
我正在使用 'django.middleware.csrf.CsrfViewMiddleware'
并且找不到如何在不影响安全性的情况下防止此问题。
I try to post parameter like
jQuery.ajax(
{
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': "{content:'xxx'}",
'dataType': 'json',
'success': rateReviewResult
}
);
However, Django return Forbidden 403. CSRF verification failed. Request aborted.
I am using 'django.middleware.csrf.CsrfViewMiddleware'
and couldn't find how I can prevent this problem without compromising security.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
您可以通过两种不同的方式发出 AJAX post 请求:
告诉您的视图不要检查 csrf 令牌。这可以通过使用装饰器
@csrf_exempt
来完成,如下所示:要在每个 AJAX 请求中嵌入 csrf 令牌,对于 jQuery 可能是:
<前><代码>$(函数 () {
$.ajaxSetup({
headers: { "X-CSRFToken": getCookie("csrftoken") }
});
});
其中
getCookie
函数从cookie中检索csrf令牌。我使用以下实现:此外,jQuery 有一个用于访问 cookie 的插件,类似的东西:
You can make AJAX post request in two different ways:
To tell your view not to check the csrf token. This can be done by using decorator
@csrf_exempt
, like this:To embed a csrf token in each AJAX request, for jQuery it may be:
Where the
getCookie
function retrieves csrf token from cookies. I use the following implementation:Also, jQuery has a plugin for accessing cookies, something like that:
我发现的最简单的方法是在数据中包含
{{csrf_token}}
值:The simplest way I have found is to include the
{{csrf_token}}
value in the data:我花了一段时间才明白如何处理代码丹尼尔发布的。但实际上您所要做的就是将其粘贴到 javascript 文件的开头。
对我来说,到目前为止最好的解决方案是:
创建一个
csrf.js
文件粘贴
csrf.js
中的代码 file在模板中引用你需要的代码
请注意,
STATIC_PREFIX/js/csrf.js
指向我的文件。我实际上正在使用{% get_static_prefix as STATIC_PREFIX %}
加载STATIC_PREFIX
变量。高级提示:如果您使用模板并且有类似
base.html
的扩展源,那么您可以直接从那里引用脚本,而不必不用再担心你的其他文件了。据我了解,这也不应该代表任何安全问题。It took me a while to understand what to do with the code that Daniel posted. But actually all you have to do is paste it at the beginning of the javascript file.
For me, the best solution so far is:
Create a
csrf.js
filePaste the code in the
csrf.js
fileReference the code in the template you need it
Notice that
STATIC_PREFIX/js/csrf.js
points to my file. I am actually loading theSTATIC_PREFIX
variable with{% get_static_prefix as STATIC_PREFIX %}
.Advanced tip: if you are using templates and have something like
base.html
where you extend from, then you can just reference the script from there and you don't have to worry anymore in there rest of your files. As far as I understand, this shouldn't represent any security issue either.简单而简短
或
docs
Simple and short
OR
docs
由于缺乏直接的答案,您只需将标头
X-CSRFToken
添加到 cookiecsrftoken
中的 ajax 请求即可。如果没有 插件,JQuery 不会执行 cookie(出于某种原因),因此:最小的代码更改是:
For lack of a straight forward answer, you just have to add the header
X-CSRFToken
to the ajax request which is in the cookiecsrftoken
. JQuery doesn't do cookies (for some reason) without a plugin so:and the minimal code change is:
如果您不将 js 嵌入到模板中,则无需任何插件的最快解决方案是:
将
,然后将
csrfmiddlewaretoken
添加到您的data
字典中:如果您确实将 js 嵌入到模板,很简单:
data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
The fastest solution without any plugins if you are not embedding js into your template is:
Put
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
before your reference to script.js file in your template, then addcsrfmiddlewaretoken
into yourdata
dictionary:If you do embed your js into the template, it's as simple as:
data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
我昨天遇到了同样的问题,认为如果有一种简单的方法来处理它,会对人们有所帮助,所以我为此编写了一个 jQuery 插件: jquery.djangocsrf。它不是在每个请求中添加 CSRF 令牌,而是将自身挂接到 AjaxSend jQuery 事件上,并将客户端 cookie 添加到标头中。
使用方法如下:
1- 包含它:
2- 在代码中启用它:
如果您的模板使用
{% csrf_token %}
,Django 总是在 cookie 中添加令牌。为了确保即使您不在模板中使用特殊标记,它也始终会添加它,请使用@ensure_csrf_cookie
装饰器:注意:我使用的是 Django 1.6.2。
I got the same issue yesterday and thought it would help people if there were a simple way to handle it, so I wrote a jQuery plugin for that: jquery.djangocsrf. Instead of adding the CSRF token in every request, it hooks itself on the AjaxSend jQuery event and adds the client cookie in a header.
Here’s how to use it:
1- include it:
2- enable it in your code:
Django always add the token in a cookie if your template uses
{% csrf_token %}
. To ensure it always adds it even if you don’t use the special tag in your template, use the@ensure_csrf_cookie
decorator:Note: I’m using Django 1.6.2.
谢谢大家的所有回答。我正在使用 Django 1.5.1。我参加聚会有点晚了,但还是到了。
我发现 Django 项目 的链接非常有用,但是我真的不想每次想要进行 Ajax 调用时都必须包含额外的 JavaScript 代码。
我喜欢 jerrykan 的响应,因为它非常简洁,只在正常的 Ajax 调用中添加一行。为了回应下面关于 Django 模板标签不可用的情况的评论,从 DOM 加载 csrfmiddlewaretoken 怎么样?
编辑 2016 年 3 月
在过去的几年里,我对这个问题的处理方法已经发生了变化。我将下面的代码(来自 Django 文档)添加到 main .js 文件并将其加载到每个页面上。完成后,您就不必再担心 ajax 的 CSRF 令牌了。
Thank you everyone for all the answers. I am using Django 1.5.1. I'm a little late to the party, but here goes.
I found the link to the Django project to be very useful, but I didn't really want to have to include the extra JavaScript code every time I wanted to make an Ajax call.
I like jerrykan's response as it is very succinct and only adds one line to an otherwise normal Ajax call. In response to the comments below his comment regarding situations when Django template tags are unavailable, how about loading up the csrfmiddlewaretoken from the DOM?
EDIT March 2016
My approach to this issue over the past few years has changed. I add the code below (from the Django docs) to a main.js file and load it on every page. Once done, you shouldn't need to worry about the CSRF token with ajax again.
在请求中包含
x-csrftoken
标头:Include
x-csrftoken
header in request:如果在阅读其他答案后,有人仍然在挣扎,请尝试以下操作:
If, after reading other answers, someone is still struggling please try this:
请注意,以这种方式执行此操作时,请确保
标记内没有
{% csrf_token %}
。然后按照解释 此处 将以下代码添加到您的 JavaScript 中Please not that when doing it this way make sure you don't have the
{% csrf_token %}
inside the<form></form>
tags. Then as explained here add the following code to your javascript只是想在这里指出,如果
GET
在您的用例中有效,那么它就不需要 CSRF 令牌。对于我的用例,使用GET
就可以了。Just want to put it out here that if
GET
works in your use case, then it wouldn't need the CSRF token. For my use case, usingGET
was OK.更多详细信息的参考链接
reference link for more detail
作为我的错误的总结:
{{ csrf_token }}
<块引用>
注意。默认 cookie 名称为
csrftoken
,但可以通过CSRF_COOKIE_NAME
设置覆盖。<块引用>
document.querySelector('[name=csrfmiddlewaretoken]').value;
但是:“从服务器接收到的标头名称通过将所有字符转换为大写、用下划线替换所有连字符以及在名称中添加 'HTTP_' 前缀来规范化” src。
因此,如果您设置
HTTP_X_CSRFTOKEN
标头,Django 会将其转换为HTTP_HTTP_X_CSRFTOKEN
,这是不正确的名称,并会引发CSRF Missed
错误。不要在ajax中使用与浏览器不同的url
127.0.0.1
&localhost
不一样!!据我所知,无需在请求正文中设置
data.append("csrfmiddlewaretoken", csrftoken);
。As a summary for my mistakes:
{{ csrf_token }}
But: "The header name received from the server is normalized by converting all characters to uppercase, replacing any hyphens with underscores, and adding an 'HTTP_' prefix to the name" src.
So, If you set the
HTTP_X_CSRFTOKEN
header, Django will convert it toHTTP_HTTP_X_CSRFTOKEN
which wis incorrect name and will raiseCSRF missed
error.Don't use url in ajax that is different than that of the browser
127.0.0.1
&localhost
are not the same !!No need to set
data.append("csrfmiddlewaretoken", csrftoken);
in the request body, As I know.