[英]403 Forbidden error when making an ajax Post request in Django framework
I am trying to integrate jquery into a web application I am making with Django framework.我正在尝试将 jquery 集成到我使用 Django 框架制作的 Web 应用程序中。 I am however having a hard time trying to make a simple
ajax
call to work.但是,我很难尝试进行简单的
ajax
调用。 My template file that contains the form html and javascript to handle the ajax call looks like:我的模板文件包含表单 html 和 javascript 来处理 ajax 调用,如下所示:
<script type="text/javascript">
$(document).ready(function() {
$( "#target" ).submit(function() {
console.log('Form was submitted');
$.ajax({
type: "POST",
url: "/hello/", // or just url: "/my-url/path/"
data: {
query: $( "#query" ).val()
},
success: function(data) {
console.log(data);
}
});
return false;
});
})
</script>
<form id="target" action="." method="post">{% csrf_token %}
<input id= "query" type="text" value="Hello there">
<input type="submit" value="Search Recent Tweets">
</form>
My views.py
that is supposed to handle the ajax call looks like:我应该处理 ajax 调用的
views.py
如下所示:
from django.core.context_processors import csrf
from django.shortcuts import render_to_response
from django.template.loader import get_template
from django.template import Context,RequestContext
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse
# access resource
def hello(request):
c = {}
c.update(csrf(request))
if request.is_ajax():
t = get_template('template.html')
#html = t.render(Context({'result': 'hello world'}))
con = RequestContext(request, {'result': 'hello world'})
return render_to_response('template.html', c, con)
else:
return HttpResponse('Not working!')
I have tried to follow the official documentation on Cross-Site Request Forgery Protection and also looked at several stackoverflow questions addressing a similar problem.我尝试遵循有关跨站点请求伪造保护的官方文档,并查看了几个解决类似问题的 stackoverflow 问题。 I have included the
{% csrf_token %}
in my html
template file but it still doesn't seem to be working.我在我的
html
模板文件中包含了{% csrf_token %}
但它似乎仍然不起作用。 I get an error in the console suggesting that the ajax call failed:我在控制台中收到一条错误消息,提示 ajax 调用失败:
POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)
How do I pass the result
variable along with my http response and get the ajax call to work smoothly?如何将
result
变量与我的 http 响应一起传递并使 ajax 调用顺利工作? Any help is deeply appreciated.任何帮助深表感谢。
Edit-1编辑-1
I wasn't supposedly passing the csrf
token along with my post request.我应该没有将
csrf
令牌与我的发布请求一起传递。 SO as per the documentation I added the following code to my template javascript:所以根据文档,我将以下代码添加到我的模板 javascript 中:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
console.log(csrftoken);
//Ajax call
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
When I refresh the template html page in the browser, I get null
in the console, suggesting that the cookie is not set or not defined.当我在浏览器中刷新模板html页面时,我在控制台中得到
null
,表明没有设置或未定义cookie。 What am I missing?我错过了什么?
Because you did not post the csrfmiddlewaretoken , so Django forbid you.因为你没有发布csrfmiddlewaretoken ,所以 Django 禁止你。this document can help you.
这份文件可以帮助你。
For the lazy guys:对于懒人:
First download cookie: http://plugins.jquery.com/cookie/首先下载cookie: http : //plugins.jquery.com/cookie/
Add it to your html:将其添加到您的 html:
<script src="{% static 'designer/js/jquery.cookie.js' %}"></script>
Now you can create a working POST request:现在您可以创建一个有效的 POST 请求:
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax(save_url, {
type : 'POST',
contentType : 'application/json',
data : JSON.stringify(canvas),
success: function () {
alert("Saved!");
}
})
The fastest solution if you are not embedding js into your template is:如果您没有将 js 嵌入到模板中,最快的解决方案是:
Put <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
把
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
before your reference to script.js file in your template, then add csrfmiddlewaretoken
into your data
dictionary: <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
在您引用模板中的 script.js 文件之前,然后将csrfmiddlewaretoken
添加到您的data
字典中:
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})
If you do embed your js into the template, it's as simple as: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
如果你确实将你的 js 嵌入到模板中,它就像:
data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
I find all previous answers on-spot but let's put things in context.我在现场找到了所有以前的答案,但让我们把事情放在上下文中。
The 403 forbidden response comes from the CSRF middleware (see Cross Site Request Forgery protection ): 403 禁止响应来自 CSRF 中间件(参见跨站请求伪造保护):
By default, a '403 Forbidden' response is sent to the user if an incoming request fails the checks performed by CsrfViewMiddleware.
默认情况下,如果传入请求未通过 CsrfViewMiddleware 执行的检查,则会向用户发送“403 Forbidden”响应。
Many options are available.许多选项可用。 I would recommend to follow the answer of @fivef in order to make jQuery add the
X-CSRFToken
header before every AJAX request with $.ajaxSetup
.我建议遵循@fivef的答案,以便 jQuery 在每个带有
$.ajaxSetup
AJAX 请求之前添加X-CSRFToken
标头。
This answer requires the cookie jQuery plugin.这个答案需要 cookie jQuery 插件。 If this is not desirable, another possibility is to add:
如果这是不可取的,另一种可能是添加:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
BUT: if the setting CSRF_COOKIE_HTTPONLY
is set to True, which often happens as the Security middleware recommends so, then the cookie is not there, even if @ensure_csrf_cookie()
is used.但是:如果设置
CSRF_COOKIE_HTTPONLY
设置为 True,这经常发生,因为安全中间件建议如此,那么即使使用了@ensure_csrf_cookie()
,cookie 也不存在。 In this case {% csrf_token %}
must be provided in every form, which produces an output such as <input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">
.在这种情况下,必须以每种形式提供
{% csrf_token %}
,这会产生诸如<input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">
。 So the csrfToken
variable would simply be obtained with:所以
csrfToken
变量可以简单地通过以下方式获得:
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
Again $.ajaxSetup
would be required of course.当然,再次需要
$.ajaxSetup
。
Other options which are available but not recommended are to disable the middleware or the csrf protection for the specific form with @csrf_exempt()
.其他可用但不推荐的选项是使用
@csrf_exempt()
禁用特定表单的中间件或 csrf 保护。
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}
You see "403 (FORBIDDEN)", because you don`t send "csrfmiddlewaretoken" parameter.您看到“403 (FORBIDDEN)”,因为您没有发送“csrfmiddlewaretoken”参数。 In template each form has this: {% csrf_token %}.
在模板中,每个表单都有这个:{% csrf_token %}。 You should add "csrfmiddlewaretoken" to your ajax data dictionary.
您应该将“csrfmiddlewaretoken”添加到您的 ajax 数据字典中。 My example is sending "product_code" and "csrfmiddlewaretoken" to app "basket" view "remove":
我的示例是将“product_code”和“csrfmiddlewaretoken”发送到应用程序“basket”视图“remove”:
$(function(){
$('.card-body').on('click',function(){
$.ajax({
type: "post",
url: "{% url 'basket:remove'%}",
data: {"product_code": "07316", "csrfmiddlewaretoken" : "{{csrf_token}}" }
});
})
});
To set the cookie, use the ensure_csrf_cookie
decorator in your view:要设置 cookie,请在您的视图中使用
ensure_csrf_cookie
装饰器:
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def hello(request):
code_here()
Make sure you aren't caching the page/view that your form is showing up on.确保您没有缓存显示表单的页面/视图。 It could be caching your CSRF_TOKEN.
它可能正在缓存您的 CSRF_TOKEN。 Happened to me!
发生在我身上!
Another approach is to add X-CSRFTOKEN header with the "{{ csrf_token }}" value like in the following example:另一种方法是添加带有“{{ csrf_token }}”值的 X-CSRFTOKEN 标头,如下例所示:
$.ajax({
url: "{% url 'register_lowresistancetyres' %}",
type: "POST",
headers: {//<==
"X-CSRFTOKEN": "{{ csrf_token }}"//<==
},
data: $(example_form).serialize(),
success: function(data) {
//Success code
},
error: function () {
//Error code
}
});
Try including this decorator on your dispatch code尝试在您的调度代码中包含此装饰器
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
def dispatch(self, request, *args, **kwargs):
return super(LessonUploadWorkView,self).dispatch(request,*args,**kwargs)
With SSL/https and with CSRF_COOKIE_HTTPONLY = False, I still don't have csrftoken in the cookie, either using the getCookie(name) function proposed in django Doc or the jquery.cookie.js proposed by fivef .使用SSL / HTTPS与CSRF_COOKIE_HTTPONLY =假,我还没有csrftoken在cookie,或者使用的getCookie(名称)中提出的功能Django的文件或提出的jquery.cookie.js fivef 。
Wtower summary is perfect and I thought it would work after removing CSRF_COOKIE_HTTPONLY from settings.py but it does'nt in https! Wtower摘要是完美的,我认为在从 settings.py 中删除 CSRF_COOKIE_HTTPONLY 后它会起作用,但它不在 https 中!
Why csrftoken is not visible in document.cookie???为什么 csrftoken 在 document.cookie 中不可见???
Instead of getting而不是得到
"django_language=fr; csrftoken=rDrGI5cp98MnooPIsygWIF76vuYTkDIt"
“django_language=fr;csrftoken=rDrGI5cp98MnooPIsygWIF76vuYTkDIt”
I get only我只得到
"django_language=fr"
“django_language=fr”
WHY?为什么? Like SSL/https removes X-CSRFToken from headers I thought it was due to the proxy header params of Nginx but apparently not... Any idea?
就像SSL/https 从头中删除 X-CSRFToken我认为这是由于 Nginx 的代理头参数,但显然不是......知道吗?
Unlike django doc Notes , it seems impossible to work with csrf_token in cookies with https.与django doc Notes不同,在带有 https 的 cookie 中使用 csrf_token 似乎是不可能的。 The only way to pass csrftoken is through the DOM by using {% csrf_token %} in html and get it in jQuery by using
传递 csrftoken 的唯一方法是通过 DOM 在 html 中使用 {% csrf_token %} 并通过使用在 jQuery 中获取它
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
It is then possible to pass it to ajax either by header ( xhr.setRequestHeader ), either by params .然后可以通过标头( xhr.setRequestHeader )或通过params将其传递给 ajax。
this works for me这对我有用
template.html模板.html
$.ajax({
url: "{% url 'XXXXXX' %}",
type: 'POST',
data: {modifica: jsonText, "csrfmiddlewaretoken" : "{{csrf_token}}"},
traditional: true,
dataType: 'html',
success: function(result){
window.location.href = "{% url 'XXX' %}";
}
});
view.py查看.py
def aggiornaAttivitaAssegnate(request):
if request.is_ajax():
richiesta = json.loads(request.POST.get('modifica'))
您必须更改文件夹 chmod 755 和文件 (.php ,.html) chmod 644。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.