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

Ann*_*080 34 django ajax jquery post

我正在尝试将jquery集成到我正在使用Django框架创建的Web应用程序中.然而,我正在努力打个简单的ajax工作电话.我的模板文件包含用于处理ajax调用的表单html和javascript,如下所示:

<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>
Run Code Online (Sandbox Code Playgroud)

views.py应该处理ajax调用看起来像:

 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!') 
Run Code Online (Sandbox Code Playgroud)

我试图遵循跨站点请求伪造保护的官方文档,并查看了几个解决类似问题的stackoverflow问题.我已将其包含{% csrf_token %}在我的html模板文件中,但它似乎仍然无效.我在控制台中收到错误,提示ajax调用失败:

POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)   
Run Code Online (Sandbox Code Playgroud)

如何将result变量与我的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);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

当我在浏览器中刷新模板html页面时,我进入null控制台,建议未设置或未定义cookie.我错过了什么?

Yoh*_*ohn 42

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


fiv*_*vef 22

对于懒惰的家伙:

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

将它添加到您的HTML:

<script src="{% static 'designer/js/jquery.cookie.js' %}"></script>
Run Code Online (Sandbox Code Playgroud)

现在您可以创建一个有效的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!");
    }

})
Run Code Online (Sandbox Code Playgroud)


Mar*_*dek 7

如果您没有将 js 嵌入到模板中,最快的解决方案是:

<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!");
            }
        })
Run Code Online (Sandbox Code Playgroud)

如果您确实将 js 嵌入到模板中,则很简单: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}


Wto*_*wer 5

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

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

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

有很多选择.我建议按照@fivef回答,让jQuery X-CSRFToken在每个AJAX请求之前添加标题$.ajaxSetup.

这个答案需要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');
Run Code Online (Sandbox Code Playgroud)

但是:如果设置CSRF_COOKIE_HTTPONLY设置为True,这通常是安全中间件建议的那样,那么即使@ensure_csrf_cookie()使用了cookie也不存在.在这种情况下,{% csrf_token %}必须以每种形式提供,这会产生诸如的输出<input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">.所以csrfToken变量只需通过以下方式获得:

var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
Run Code Online (Sandbox Code Playgroud)

当然$.ajaxSetup还需要.

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


And*_*wPt 5

data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}
Run Code Online (Sandbox Code Playgroud)

您看到“403 (FORBIDDEN)”,因为您没有发送“csrfmiddlewaretoken”参数。在模板中,每个表单都有这个:{% csrf_token %}。您应该将“csrfmiddlewaretoken”添加到您的 ajax 数据字典中。我的示例是将“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}}" }
        });
    })
});
Run Code Online (Sandbox Code Playgroud)