Django 1.3 中的 Ajax CSRF 问题

发布于 2024-10-28 02:39:55 字数 371 浏览 4 评论 0原文

根据 django 文档,对于 1.3 中的 ajax post 请求(至少使用 Jquery),我们只需要添加此 片段 到主 js 文件。此代码片段从 cookie 中获取 csrftoken,然后为所有 ajax 请求设置它。这是可行的,但是如果 cookie 中不存在 csrftoken 怎么办?我认为 render_to_response 和 render 都会自动检查会话中是否存在 csrftoken,并在 token 不存在时为我们设置它。但他们不是。那么,我需要自己实现吗?或者也许还有另一种方法来处理ajax csrf保护?

According to django documentation, for ajax post request in 1.3 (at least with Jquery), we just need to add this snippet to main js file. This snippet get csrftoken from cookies, and then set up it for all ajax request. That's work, but what if csrftoken don't exist in cookies? I thought render_to_response and render both automatically checks if csrftoken in sessions, and set it for us, if token not there. But they are not. So, i need to implement it by myself? Or maybe there is another way to handle ajax csrf protection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

皓月长歌 2024-11-04 02:39:55

当页面上没有已使用 {% 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()})

仅供参考 - 这正是该装饰器的作用。

When there is no form on a page that is already using {% csrf_token %}, the cookie will not be sent. Therefore, as you noted, you will get an error when you attempt to use Ajax on such a page. This will lead to erratic behavior if you have a site with a mix of pages with various combinations of forms and ajax posts.

This has already been reported and fixed: https://code.djangoproject.com/ticket/15354

The solution in the patch, will should roll out with 1.3.1, is the ensure_cookie_csrf decorator. That decorator does not exist in 1.3 or 1.2.5

No need to wait, however. Just add this line to any view which contains AJAX posts a CSRF form:

request.META["CSRF_COOKIE_USED"] = True

Example:

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

FYI - this is exactly what that decorator does.

北斗星光 2024-11-04 02:39:55

如果在模板中使用模板标记 {% csrf_token %} 来生成请求,或者如果您调用 get_token (使用来自 django.middleware.csrf 的 request 对象作为参数)。

get_token 函数在 request 对象上设置元信息,该对象又告诉 django.middleware.csrf.CsrfViewMiddleware 中间件设置 cookie。

Your cookie will only contain the CSRF token, if either the template tag {% csrf_token %} was used in the template to generate the request, or if you call get_token (with the request object as argument) from django.middleware.csrf.

The get_token function sets metainformation on the request object that in turn tells the django.middleware.csrf.CsrfViewMiddleware middleware to set the cookie.

无畏 2024-11-04 02:39:55

对于 Ajax,您应该在每个请求中传递 csrf 令牌。对于 jQuery,我使用以下代码:

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

As for Ajax, you should pass the csrf token with every request. For jQuery, I use the following code:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if(!options.crossDomain) {
        if(options.data) {
            options.data += "&";
        } else {
            options.data = "";
        }
        options.data += "csrfmiddlewaretoken={{csrf_token}}";
    }
});
╰つ倒转 2024-11-04 02:39:55

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

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

然后,您可以通过 JQuery 的 Serialize 函数在 JavaScript 中使用它:

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

您甚至可以在该隐藏表单中使用隐藏字段,这样您就不必使用字符串连接来构建 POST 数据。

One way that I've found to get around this is by using a preexisting form as a starter point for your AJAX data.

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

Then you can use this in your JavaScript via JQuery's Serialize function:

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

You can even use hidden fields within that hidden form so that you don't have to use string concatenation to built your POST data.

腻橙味 2024-11-04 02:39:55

如果您使用 @csrf_protect 装饰器,请确保带有表单的视图和正在发布数据的视图都使用该装饰器。

我有类似的问题。我只在帖子视图上有@csrf_protect,它在本地测试工作正常,但是当我上线时,出现了 403 验证失败的问题,将装饰器添加到页面视图修复了此问题

If you are using the @csrf_protect decorator, make sure that both the view with the form and the view that the data is being posted to use the decorator.

I had a similar issue. I only had @csrf_protect on the post view which worked fine testing locally but when i went live o got a 403 verification failed issue adding the decorator tot he page view fixed this

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文