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)
如何将result
variables与我的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">
。 所以csrfToken
variables只能通过以下方式获得:
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。