使用Ajax POST请求,Django CSRF检查失败 [英] Django CSRF check failing with an Ajax POST request

查看:123
本文介绍了使用Ajax POST请求,Django CSRF检查失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以通过我的AJAX帖子使用一些符合Django的CSRF保护机制的帮助。我按照这里的指示:



http://docs.djangoproject.com/en/dev/ref/contrib/csrf/



我已经复制了AJAX完全在该页面上的示例代码:



http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax



我在 xhr.setRequestHeader 调用之前,打印 getCookie('csrftoken')的内容,并确实填写有一些数据。我不知道如何验证该令牌是否正确,但我很鼓励它找到并发送东西。



但Django仍然拒绝我的AJAX帖子。



这是我的JavaScript:

  $。post(/ memorize /,data,function(result){
if(result!=failure){
get_random_card();
}
else {
alert无法保存卡数据。);
}
});

以下是我从Django看到的错误:


[23 / Feb / 2011 22:08:29]POST / memorize / HTTP / 1.1403 2332


我确定我错过了一些东西,也许很简单,但我不知道是什么。我已经搜索了SO,看到一些关于通过 csrf_exempt 装饰器关闭CSRF检查的信息,但是我觉得没有吸引力。我已经尝试了它,它的作品,但我宁愿让我的POST工作的方式Django的设计来预期,如果可能的话。



只是为了防万一这是有帮助的,这是我的观点在做什么的要点:

  def myview(request):

profile = request.user.profile

如果request.method =='POST':

处理帖子...

return HttpResponseRedirect('/ memorize /')
else:#request.method =='GET'

ajax = request.GET.has_key('ajax')


一些不必要的代码...


如果ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:

获取与页面内容一起发送的数据


return render_to_response('记住/ memorize.html',
我的数据
context_instance = RequestContext(request))

感谢您的回复!

解决方案

实际解决方案 p>

好的,我设法追踪问题。它在于Javascript(如我在下面建议的)代码。



您需要的是:

 $。ajaxSetup({
beforeSend:function(xhr,settings){
function getCookie(name){
var cookieValue = null;
if (document.cookie&& document.cookie!=''){
var cookies = document.cookie.split(';');
for(var i = 0; i&这个cookie字符串是以我们想要的名字开头的?
if(cookie.substring((...));
var cookie = jQuery.trim 0,name.length + 1)==(name +'=')){
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
返回cookieValue;
}
如果(! (/^http:.*/.test(settings.url)|| /^https:.*/.test(settings.url))){
//只将令牌发送到相对URL,即本地。
xhr.setRequestHeader(X-CSRFToken,getCookie('csrftoken'));
}
}
});

而不是官方文档中发布的代码:
http://docs.djangoproject.com/en/1.2/ref/contrib/csrf/#ajax



工作代码来自此Django条目: http://www.djangoproject.com/weblog/2011/feb/08/security/



所以一般的解决方案是:使用ajaxSetup处理程序的ajaxSend处理程序。我不知道为什么它的作品。但是它适用于我:)



上一篇文章(无答案)



我真的遇到了同样的问题。



更新到Django 1.2.5后,Django 1.2.4(AJAX wasn)中的AJAX POST请求没有错误不要以任何方式保护,但是它的工作很正常)。



就像OP一样,我尝试过在Django文档中发布的JavaScript代码段。我使用的是jQuery 1.5。我也使用django.middleware.csrf.CsrfViewMiddleware中间件。



我试图跟随中间件代码,我知道它失败了: / p>

  request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN','')
/ pre>

然后

  if request_csrf_token!= csrf_token:
return self._reject(request,REASON_BAD_TOKEN)

这个if是真的,因为 request_csrf_token为空。



基本上这意味着标题没有设置。那么这个JS行有什么问题吗?

  xhr.setRequestHeader(X-CSRFToken,getCookie('csrftoken') ); 



我希望提供详细信息将帮助我们解决问题:)


I could use some help complying with Django's CSRF protection mechanism via my AJAX post. I've followed the directions here:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/

I've copied the AJAX sample code they have on that page exactly:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

I put an alert printing the contents of getCookie('csrftoken') before the xhr.setRequestHeader call and it is indeed populated with some data. I'm not sure how to verify that the token is correct, but I'm encouraged that it's finding and sending something.

But Django is still rejecting my AJAX post.

Here's my JavaScript:

$.post("/memorize/", data, function (result) {
    if (result != "failure") {
        get_random_card();
    }
    else {
        alert("Failed to save card data.");
    }
});

Here's the error I'm seeing from Django:

[23/Feb/2011 22:08:29] "POST /memorize/ HTTP/1.1" 403 2332

I'm sure I'm missing something, and maybe it's simple, but I don't know what it is. I've searched around SO and saw some information about turning off the CSRF check for my view via the csrf_exempt decorator, but I find that unappealing. I've tried that out and it works, but I'd rather get my POST to work the way Django was designed to expect it, if possible.

Just in case it's helpful, here's the gist of what my view is doing:

def myview(request):

    profile = request.user.profile

    if request.method == 'POST':
        """
        Process the post...
        """
        return HttpResponseRedirect('/memorize/')
    else: # request.method == 'GET'

        ajax = request.GET.has_key('ajax')

        """
        Some irrelevent code...
        """

        if ajax:
            response = HttpResponse()
            profile.get_stack_json(response)
            return response
        else:
            """
            Get data to send along with the content of the page.
            """

        return render_to_response('memorize/memorize.html',
                """ My data """
                context_instance=RequestContext(request))

Thanks for your replies!

解决方案

Real solution

Ok, I managed to trace the problem down. It lies in the Javascript (as I suggested below) code.

What you need is this:

$.ajaxSetup({ 
     beforeSend: function(xhr, settings) {
         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;
         }
         if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
             // Only send the token to relative URLs i.e. locally.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         }
     } 
});

instead of the code posted in the official docs: http://docs.djangoproject.com/en/1.2/ref/contrib/csrf/#ajax

The working code, comes from this Django entry: http://www.djangoproject.com/weblog/2011/feb/08/security/

So the general solution is: "use ajaxSetup handler instead of ajaxSend handler". I don't know why it works. But it works for me :)

Previous post (without answer)

I'm experiencing the same problem actually.

It occurs after updating to Django 1.2.5 - there were no errors with AJAX POST requests in Django 1.2.4 (AJAX wasn't protected in any way, but it worked just fine).

Just like OP, I have tried the JavaScript snippet posted in Django documentation. I'm using jQuery 1.5. I'm also using the "django.middleware.csrf.CsrfViewMiddleware" middleware.

I tried to follow the the middleware code and I know that it fails on this:

request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

and then

if request_csrf_token != csrf_token:
    return self._reject(request, REASON_BAD_TOKEN)

this "if" is true, because "request_csrf_token" is empty.

Basically it means that the header is NOT set. So is there anything wrong with this JS line:

xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

?

I hope that provided details will help us in resolving the issue :)

这篇关于使用Ajax POST请求,Django CSRF检查失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆