43

我正在尝试将 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>

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

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

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

如何将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);
        }
    }
});

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

4

12 回答 12

52

因为你没有发布csrfmiddlewaretoken,所以 Django 禁止你。 本文档可以帮助您。

于 2013-10-12T10:25:07.713 回答
26

对于懒人:

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

将其添加到您的 html 中:

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

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

})
于 2014-09-29T13:02:09.263 回答
7

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

在您的模板中对 script.js 文件的引用之前放置<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>,然后添加csrfmiddlewaretoken到您的data字典中:

$.ajax({
            type: 'POST',
            url: somepathname + "do_it/",
            data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
            success: function() {
                console.log("Success!");
            }
        })

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

于 2018-08-09T12:14:18.947 回答
6

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

403 禁止响应来自 CSRF 中间件(请参阅Cross Site Request Forgery protection):

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

有很多选择。我建议遵循@fivef 的答案,以便让 jQueryX-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');

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

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

当然,再次$.ajaxSetup需要。

其他可用但不推荐的选项是禁用中间件或使用@csrf_exempt().

于 2015-05-13T09:12:37.780 回答
5
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}

您会看到“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}}" }
        });
    })
});
于 2019-05-15T10:16:35.190 回答
2

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

于 2015-01-16T05:54:48.607 回答
2

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

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def hello(request):
    code_here()
于 2013-10-12T16:42:59.473 回答
2

另一种方法是添加带有“{{ 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
            }
        });
于 2019-10-30T20:41:32.450 回答
0

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

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)
于 2017-07-05T15:11:36.527 回答
0

这对我有用

模板.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' %}";
        }
});

视图.py

def aggiornaAttivitaAssegnate(request):
    if request.is_ajax():
        richiesta = json.loads(request.POST.get('modifica'))
于 2021-01-23T10:54:49.320 回答
0

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

Wtower摘要是完美的,我认为从 settings.py 中删除 CSRF_COOKIE_HTTPONLY 后它会起作用,但它在 https 中没有!

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

而不是得到

“django_language=fr;csrftoken=rDrGI5cp98MnooPIsygWIF76vuYTkDIt”

我只得到

“django_language=fr”

为什么?就像SSL/https 从标头中删除 X-CSRFToken我认为这是由于 Nginx 的代理标头参数,但显然不是...任何想法?

django doc Notes不同,在带有 https 的 cookie 中使用 csrf_token 似乎是不可能的。传递 csrftoken 的唯一方法是通过 DOM 在 html 中使用 {% csrf_token %} 并在 jQuery 中使用

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

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

于 2017-10-03T13:01:49.850 回答
-3

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

于 2016-04-11T16:13:26.657 回答