Django / JQuery CSRF:403错误

时间:2013-03-30 17:16:07

标签: jquery django csrf django-csrf

我一直从Django得到403错误。

我设置我的settings.py以使用CSRF保护,并在我的模板中使用了csrf_token标记。

这是我在HTML标题后面包含的JS文件:http://bpaste.net/show/87791/

使用Firebug我可以检查CSRF cookie是否存在。稍后在页面上,用户单击触发此代码的按钮:

myFunction: function() {
  $.ajax({
  type: 'POST',
  url: window.localtion.href + 'myajaxview',
  async: false
  });
}

我正在使用从TemplateView继承的简单类视图来显示此页面。 'myajaxview'继承自View和JSON Mixin。但是,由于django无法验证CSRF令牌,因此永远不会执行其代码。

在我看来,ajax不会发送带有POST标头的令牌。或者我错过了什么?

编辑:我在调用$ .ajax()POST函数之前移动了$ .ajaxSetup调用,但它运行正常。我试图把它移到其他地方但它失败了。我认为问题与Ajax的关系比Django更多。 所以,我的问题仍然存在,我不想在每次$ .ajax调用之前调用$ .ajaxSetup,我不认为这是事情的完成方式,我不想重复自己。所以这只是一种解决方法,我要求解决方案。

5 个答案:

答案 0 :(得分:3)

myFunction: function() {
  $.ajax({
  type: 'POST',
  data: { 
    'csrfmiddlewaretoken': '{{csrf_token}}'
  }, 
  url: '/myajaxview/',
  async: false
  });
}

答案 1 :(得分:2)

这是我认为您正在寻找的代码片段

var csrfToken = $('input[name="csrfmiddlewaretoken"]').val();
$.ajax({
    url: 'blah.com/',
    //snipped for brevity
    csrfmiddlewaretoken: csrfToken,
    success: function(data){ doStuff(); }
});

这是我使用的,以便能够对django应用程序进行jquery ajax调用。 希望它有效!

答案 2 :(得分:1)

感谢您的帮助。答案非常讨厌,我通过一个简单的例子开始测试ajaxSetup + ajax,然后我添加了更多的复杂性以匹配我的原始代码。

这是因为jquery-tools。当我开始使用bootstrap-twitter时,我看到他们建议将javascript包含在页面末尾。所以我也把jquery-tools.js包含在那里。我几乎不知道在这个脚本文件中调用了$ .ajaxSetup,它已经覆盖了我自己。

解决方案是将jquery工具包含在顶层。但是在这一点上,我不确定它会与我的代码冲突多少。因为我需要为每个ajax请求提供ajaxSetup。

我花了一天时间才发现,我在#jquery和#django上,很多人都试图找出解决方案。如果你得到一个你无法分享的复杂代码库,你想要解决的问题是我的建议:尝试让最简单的例子工作并改变它,直到它与你的失败设置相匹配。它将节省每个人的时间,尤其是你自己的时间。

答案 3 :(得分:0)

首先,您是否检查过CSRF代码是否实际发送到服务器?如果是,服务器是否期望散列位于post值或标题中?现在您设置请求标头。 如果两者都无法解决问题,请验证服务器是否知道正确的哈希值。当客户端发送正确的散列并且服务器将NULL作为散列时,则验证将失败。

答案 4 :(得分:0)

我通过在DOM准备就绪时计算令牌的值来解决问题,并且AJAX重新加载。

javascript代码使用reload_ajax()函数来处理令牌,以及在初始页面加载和后续AJAX调用时需要刷新的任何其他内容。

<script type="text/javascript">

function reload_ajax() {
    // Useful on initial page load, and after calling AJAX.
    $("input#token").val("{{ csrf_token }}");
}

$(document).ready(function() {
    $("form#stats").unbind("submit");      // Prevents calling document-ready multiple times
    $("form#stats").submit(function(event) {
        event.preventDefault();
        $.ajax({
            type:"POST",
            url: $(this).attr("action"),
            data: $(this).serialize(),     // Serialize the form
            dataType: "json",
            success: function(response){
                $("#stats_ajax").html(response.html);  // Object to refresh after AJAX 
                reload_ajax();
            }
        });
        return false;
    });

    reload_ajax();
});
</script>

我使用了两个HTML文件, 在main.html中,我有上面的javascript代码,以及以下内容:

<div id="stats_ajax">
    {% include "stats_ajax.html" %}
</div>

在stats_ajax.html中,我有实际的表格(以及我需要刷新的其他内容)

<form id="stats" action="/main/" method="post">
    <!-- The value will be inserted when the DOM reloads. -->
    <input id="token" type="hidden" name="csrfmiddlewaretoken" value="" />
    <!-- Other input elements -->
    <button type="submit">Submit</button>
</form>

在我的views.py文件中,

# Not all imports may be needed for this example
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.template.loader import render_to_string
import json

def main(request):
    # This request should only be posting AJAX
    if request.is_ajax():
        data = {}
        data["message"] = "Awesome"
        # This is the template to load on the DOM object to update
        html = render_to_string("stats_ajax.html", data)
        res = {"html": html}
        return HttpResponse(json.dumps(res), mimetype='application/json')

    # Handle GET to this view
    return redirect("/main")

最后,我的urls.py有

# Replace "application_name" with your own value
url(r'^main', 'application_name.views.main'),