与django和ajax的http 403错误

时间:2011-07-19 16:03:06

标签: ajax django csrf

我正在通过'Django 1.0网站开发'工作,并在使用表单时遇到问题。服务器抱怨有关'csrf'的事情。我可以在form-tag之后添加{% csrf_token %}来解决它。我已经阅读了djangoproject.com上的文档,但我不得不承认我并不完全理解这里到底发生了什么。我不使用中间件类。

当我到达ajax时,真正的问题就开始了。我按照书中的说明写信,但服务器开始抱怨:

"POST /save/?ajax HTTP/1.1" 403 2332

以下是可能导致问题的代码:

function bookmark_save() {
var item = $(this).parent();
var data = {
    url: item.find("#id_url").val(),
    title: item.find("#id_title").val(),
    tags: item.find("#id_tags").val()
};
$.post("/save/?ajax", data, function (result) {
    if (result != "failure") {
        item.before($("li", result).get(0));
        item.remove();
        $("ul.bookmarks .edit").click(bookmark_edit);
    }
    else {
        alert("Failed to validate bookmark before saving.");
    }
});
return false;

}

'/ save /& amp; ajax'由

处理
if ajax:
    return render_to_response('bookmark_save_form.html', variables)

这里是bookmark_save_form.html:

<form id="save-form" method="post" action="/save/">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="save" />
</form>

据我所知,我必须通过POST请求传递csrf_token。但我不知道如何。

对此的任何建议都会很棒。

5 个答案:

答案 0 :(得分:1)

我目前正在编写本书,并遇到了完全相同的问题,BTW。不是第一次!基本上发生的事情是没有通过Ajax请求传递csrf令牌。所以,简短而简单的答案是你需要包含csrf令牌是你的ajax调用。这是通过以下代码块完成的:https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax

jQuery(document).ajaxSend(function(event, 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;
}
function sameOrigin(url) {
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});

然后我将其作为.js文件包含在我的user_page.html中。在那之后,我可以不受惩罚地进行Ajax调用!

答案 1 :(得分:0)

我从已经完成的项目中提取了这个。这是一个联系表单模板。请注意,这是django。另请参阅django书http://www.djangobook.com/en/2.0/。本书回答了我的所有问题。它遍及一切。这显示了如何放入csrf令牌(在模板中):

<head> 
    <title>Contact Us</title> 
</head> 
<body> 
    <h1>Contact us</h1> 

{% if form.errors %}
    <p style="color: red;"> 
        Please correct the error{{ form.errors|pluralize }} below.
    </p> 
{% endif %}

<form action="" method="post"> 
    {% csrf_token %}
    <ul> 
        {{ form.as_ul }}
    </ul> 
    <input type="submit" value="Submit"> 
</form> 
</body> 

此外,将您的值更改为提交而不是保存,而不是/ save / for action使用post .....可能会使其正常工作。

答案 2 :(得分:0)

我正在完成这本书并遇到了同样的问题。这是最简单的解决方案,其优点是不会禁用Django的csrf保护,或者必须包含装饰器或者使用'ensure_csrf_cookie'等实用程序。它只是传递令牌:

在您创建的.js文件中,用于保存自定义jquery脚本,将以下对添加到bookmark_save()函数中的“data”var中:

csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].val()

因此得到的bookmark_save函数如下所示:

function bookmark_save() {
    var item = $(this).parent();
    var data = {
        url: item.find("#id_url").val(),
        title: item.find("#id_title").val(),
        tags: item.find("#id_tags").val(),
        csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].val()
    };
    $.post("/save/?ajax", data, function (result) {
        if (result != "failure") {
            item.before($("li", result).get(0));
            item.remove();
            $("ul.bookmarks .edit").click(bookmark_edit);
        }
        else {
            alert("Failed to validate bookmark before saving.");
        }
    });
    return false;
}

答案 3 :(得分:0)

来自django.views.decorators.csrf import csrf_exempt

<div id="myDiv" runat="server" ClientIDMode="static" ></div>

答案 4 :(得分:-1)

创建一个Javascript文件。我不知道如何格式化代码 - 抱歉。然后在Jquery之后加载它。

描述here