【问题标题】:Ajax CSRF problem in Django 1.3Django 1.3 中的 Ajax CSRF 问题
【发布时间】:2011-07-26 20:32:33
【问题描述】:

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

【问题讨论】:

    标签: ajax django csrf


    【解决方案1】:

    当已经使用 {% 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()})
    

    仅供参考 - 这正是装饰器所做的。

    【讨论】:

    • 根据CSRF Django documentation,ensure_cookie_csrf 装饰器是 Django 1.4 的新特性。
    • 是的,ensure_csrf_cookie 装饰器登陆 Django 1.4。不幸的是 1.3.1 中没有
    【解决方案2】:

    如果在模板中使用模板标签{% csrf_token %} 来生成请求,或者如果您从@987654324 调用get_token(使用request 对象作为参数),您的cookie 将只包含CSRF 令牌@。

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

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

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

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

        【讨论】:

          【解决方案5】:

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

          我遇到了类似的问题。我在帖子视图上只有@csrf_protect ,它在本地测试良好,但是当我上线时遇到一个 403 验证失败的问题,将装饰器添加到他的页面视图修复了这个

          【讨论】:

            猜你喜欢
            • 2017-07-01
            • 2011-04-24
            • 2023-03-22
            • 1970-01-01
            • 2011-11-12
            • 2011-09-05
            • 2019-05-31
            • 2011-11-13
            • 2011-08-31
            相关资源
            最近更新 更多