【问题标题】:how to make a proper ajax call in javascript to django framework with csrf protection?如何在javascript中对具有csrf保护的django框架进行正确的ajax调用?
【发布时间】:2015-12-24 05:08:33
【问题描述】:

在将其标记为重复之前,请仔细阅读,因为我已经经历了很多堆栈溢出问题,但找不到合适的解决方案。

所以我面临的问题是我是 django 的新手,并且了解了 POST 请求的 CSRF 保护。我已经在基于非 ajax 的页面上成功实现了这些调用。但是我正在处理的当前项目是一个单页应用程序。所以所有的调用都是通过 ajax 并且在 vanila JS 中不使用任何库。我面临的问题是,对于第一个请求,我获得了在模板中生成的有效 CSRF 令牌。但是在第一次 ajax 调用之后 CSRF 令牌发生了变化。所以我想知道在这种情况下,django 中的正确方法是什么。我应该以某种方式让所有请求都以 CSRF 令牌响应并将它们保存在 JS 变量中吗?

目前还有两个页面。第一个是没有 ajax 调用的简单登录模板。它使用凭据发布到主页,如果有效,则完成。但在家里有多种形式。并且提交其中任何一个都会更改令牌,所以我该如何处理这样的情况。

PS:我更喜欢纯 JS 中的代码而不是 jquery 或任何其他框架,并且不想禁用 csrf 保护。

我已经认为将 CSRF 令牌存储在 cookie 或会话变量中,这将违背令牌的全部目的。

请附上我可以学习的示例代码。

【问题讨论】:

  • 是的,您应该将其存储在 JS 变量中并与 ajax 请求一起发送。您到底尝试过哪些不起作用的方法?
  • @dan-klasson 我没有尝试过,但想知道正确的处理方式。如果基于 ajax 的表单与普通表单混合,这种情况会怎样。这种情况下的解决方案是什么?

标签: javascript ajax django django-csrf


【解决方案1】:

我面临的问题是我收到的第一个请求 我在模板中生成的有效 CSRF 令牌。但之后 首先 ajax 调用 CSRF 令牌更改。

我不相信这是真的。否则,如果用户打开多个选项卡,任何 django 应用程序都会停止工作。

这是我在网络应用上使用的解决方案。它按预期工作,但我没有遵循从 cookie 中获取令牌值的官方建议。为什么?更少的代码。

myapp/templatetags/csrf_ajax.html

from django import template

register = template.Library()


@register.inclusion_tag('myapp/_csrf_ajax.html')
def csrf_ajax():
    # https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

    return {}

_csrf_ajax.html

<script>
(function () {
    var csrf_token = "{{ csrf_token }}";
    function csrfSafeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrf_token);
            }
        }
    });
})();
</script>

然后我在每个需要 CSRF ajax 设置的页面中使用这个模板标签。

{% csrf_ajax %}

【讨论】:

    【解决方案2】:

    csrttoken 存储在 cookie 中,它不会随着每个 ajax 请求而改变。我在 js 文件中有这段代码,并将其添加到需要发送 ajax 发布请求的任何页面(它使用 jQuery 和 cookie,如果您不想使用外部库,则需要将其转换为纯 JavaScript):

    var csrftoken = $.cookie('csrftoken');
    
    function csrfSafeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-14
      • 2017-09-05
      • 2012-11-01
      • 2017-06-14
      • 2020-04-15
      • 2012-06-28
      • 2016-02-10
      • 2017-12-21
      相关资源
      最近更新 更多