403在Django框架中发出ajax Post请求时出现禁止的错误

我正在尝试将jquery集成到我正在使用Django框架的Web应用程序中。 然而,我正在努力做一个简单的ajax调用工作。 包含表单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> 

我应该处理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!') 

我试图遵循关于跨站点请求伪造保护的官方文档,并且还查看了几个解决类似问题的计算器问题。 我已经在我的html模板文件中包含了{% csrf_token %} ,但它似乎仍然没有工作。 我在控制台中得到一个错误提示ajax调用失败:

 POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN) 

如何将resultvariables与我的http响应一起传递,并使ajax调用顺利进行? 任何帮助深表谢意。

编辑-1

我不应该传递csrf标记与我的发布请求一起。 所以根据文档我将下面的代码添加到我的模板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); } } }); 

当我在浏览器中刷新模板html页面时,我在控制台中得到null ,提示cookie没有设置或没有定义。 我错过了什么?

因为你没有发布csrfmiddlewaretoken ,所以Django禁止你。 这个文件可以帮助你。

对于懒惰的家伙:

首先下载cookie: http : //plugins.jquery.com/cookie/

将它添加到你的html:

 <script src="{% static 'designer/js/jquery.cookie.js' %}"></script> 

现在你可以创build一个工作的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!"); } }) 

我现场find所有以前的答案,但让我们把事情放在上下文中。

403禁止响应来自CSRF中间件(请参阅跨站点请求伪造防护 ):

默认情况下,如果传入的请求未通过CsrfViewMiddleware执行的检查,则会向用户发送“403 Forbidden”响应。

许多选项可用。 我build议遵循@fivef的回答,以便让jQuery在每个AJAX请求之前用$.ajaxSetup添加X-CSRFToken标头。

这个答案需要cookie jQuery插件。 如果这是不可取的,另一种可能性是增加:

 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'); 

但是:如果设置CSRF_COOKIE_HTTPONLY设置为True,这通常是安全中间件推荐的,那么即使使用@ensure_csrf_cookie() ,cookie也不存在。 在这种情况下,必须在每种forms中提供{% csrf_token %} ,从而生成诸如<input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden"> 。 所以csrfTokenvariables只能通过以下方式获得:

 var csrftoken = $('input[name="csrfmiddlewaretoken"]').val(); 

当然需要$.ajaxSetup

其他可用但不推荐的选项是使用@csrf_exempt()来禁用特定表单的中间件或csrf保护。

要设置cookie,请在视图中使用ensure_csrf_cookie装饰器:

 from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def hello(request): code_here() 

尝试在你的调度代码中包含这个装饰器

 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) 

确保你没有caching你的表单显示的页面/视图。 它可能会caching您的CSRF_TOKEN。 发生在我身上!

使用SSL / https和CSRF_COOKIE_HTTPONLY = False,我仍然没有使用django Doc中提出的getCookie(name)函数或者fivef提出的jquery.cookie.js ,在cookie中没有csrftoken 。

Wtower总结是完美的,我认为这将工作后从settings.py中删除CSRF_COOKIE_HTTPONLY,但它不会在https!

为什么csrftoken在document.cookie中不可见?

而不是得到

“django_language = fr; csrftoken = rDrGI5cp98MnooPIsygWIF76vuYTkDIt”

我只得到

“django_language = FR”

为什么? 像SSL / HTTPS从标题中删除X-CSRFToken我认为这是由于Nginx的代理头params,但显然不是…任何想法?

不像Django的文档注释 ,似乎不可能与https cookie中的csrf_token一起使用。 传递csrftoken的唯一方法是通过使用html中的{%csrf_token%}通过DOM使用,并通过使用jQuery

 var csrftoken = $('input[name="csrfmiddlewaretoken"]').val(); 

然后可以通过header( xhr.setRequestHeader )将它传递给ajax,或者通过params 。

您必须更改您的文件夹chmod 755和文件(.php,.html)chmod 644。