2011-03-31 93 views
6

根据django文档,对于1.3中的ajax post请求(至少在jquery中),我们只需要将这snippet添加到主js文件。这段代码从cookie中获取csrftoken,然后为所有ajax请求设置它。这是工作,但如果cookie中不存在csrftoken呢?我认为render_to_response和render都会自动检查会话中是否有csrftoken,如果token不存在,就为我们设置它。但他们不是。那么,我需要自己来执行它?或者也许有另一种方法来处理Ajax csrf保护?Django 1.3中的Ajax CSRF问题

回答

3

你的cookie将只包含CSRF令牌,如果有一个模板标签{% csrf_token %}在模板中使用生成请求,或者如果你调用get_token(与request对象作为参数)从django.middleware.csrf

get_token函数设置request对象上的元信息,该对象又会通知django.middleware.csrf.CsrfViewMiddleware中间件设置cookie。

3

对于Ajax,您应该在每次请求时都传递csrf标记。 jQuery的,我用下面的代码:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
    if(!options.crossDomain) { 
     if(options.data) { 
      options.data += "&"; 
     } else { 
      options.data = ""; 
     } 
     options.data += "csrfmiddlewaretoken={{csrf_token}}"; 
    } 
}); 
11

当有一个已使用{%csrf_token%}在页面上没有形成,该cookie不会被发送。因此,正如您所指出的那样,当您尝试在这样的页面上使用Ajax时会出现错误。这会导致不稳定的行为,如果你有一个网站混合形式和ajax职位的各种组合的网站。

这已上报并固定:https://code.djangoproject.com/ticket/15354

在补丁的解决方案,将要推出与1.3.1,是ensure_cookie_csrf装饰。该装饰器不存在于1.3或1.2.5中

然而,不需要等待。只是这行添加到其中包含AJAX职位CSRF形式的任何观点:

request.META["CSRF_COOKIE_USED"] = True 

例子:

def calculator(request): 
    request.META["CSRF_COOKIE_USED"] = True 
    return render_to_response('calc.html', {'form': CalcForm()}) 

仅供参考 - 这是装饰究竟是干什么的。

+0

根据[CSRF Django文档](https:// docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views。decorators.csrf.ensure_csrf_cookie),ensure_cookie_csrf修饰器是Django 1.4的新增功能。 – 2012-05-14 16:33:15

+1

是的,ensure_csrf_cookie装饰器在Django 1.4中着陆。很遗憾,不在1.3.1中 – bjunix 2012-05-22 12:41:26

1

我发现解决这个问题的一种方法是使用预先存在的表单作为AJAX数据的起始点。

<form id="ajax_form" stye="display: none;">{% csrf_token %}</form> 

然后你就可以通过JQuery的序列化功能,在你的JavaScript使用:

var data = $('#ajax_form').serialize(); 
data += "&mydata=69"; 

你甚至可以使用隐藏的表单中的隐藏字段,这样你就不必使用字符串连接到内置你的POST数据。

1

如果您使用的是@csrf_protect修饰器,请确保包含表单的视图和数据被发布为使用修饰器的视图。

我有类似的问题。我只有@csrf_protect在发布视图工作正常在本地测试,但是当我去现场o得到了403验证失败的问题添加装饰器他页面视图固定此