0

我不断从 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 的关系更大。所以,我的问题仍然存在,我不想把 $.ajaxSetup 调用放在每个 $.ajax 调用之前,我不认为这是事情的处理方式,我不想重复自己。所以这只是一种解决方法,我正在寻求解决方案。

4

5 回答 5

3
myFunction: function() {
  $.ajax({
  type: 'POST',
  data: { 
    'csrfmiddlewaretoken': '{{csrf_token}}'
  }, 
  url: '/myajaxview/',
  async: false
  });
}
于 2013-03-31T01:52:40.937 回答
2

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

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

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

于 2013-03-31T00:05:42.627 回答
1

感谢您的帮助。答案真的很讨厌,我从一个简单的示例开始测试 ajaxSetup + ajax 发现它,然后我添加了更多复杂性以匹配我的原始代码。

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

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

我花了一天的时间才发现,我在#jquery 和#django 上,很多人不遗余力地试图找出解决方案。如果您遇到无法共享的复杂代码库以及想要解决的问题,我的建议是:尝试使最简单的示例正常工作并更改它,直到它与您失败的设置相匹配。这将节省每个人的时间,尤其是您自己的时间。

于 2013-03-31T15:44:41.850 回答
0

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

于 2013-03-30T17:30:20.443 回答
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>

In my views.py file,

# 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")

Finally, my urls.py has

# Replace "application_name" with your own value
url(r'^main', 'application_name.views.main'),
于 2014-01-16T08:22:23.567 回答