如何在javascript中对具有csrf保护的django框架进行正确的ajax调用?

Posted

技术标签:

【中文标题】如何在javascript中对具有csrf保护的django框架进行正确的ajax调用?【英文标题】:how to make a proper ajax call in javascript to django framework with csrf protection? 【发布时间】: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 的表单与普通表单混合,这种情况会怎样。这种情况下的解决方案是什么? 【参考方案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);
        
    
);

【讨论】:

以上是关于如何在javascript中对具有csrf保护的django框架进行正确的ajax调用?的主要内容,如果未能解决你的问题,请参考以下文章

Django中的X-editable内联编辑-如何获得CSRF保护?

保护 oauth 不记名令牌免受 javascript 应用程序中的 XSS、CSRF 等攻击

如何绕过csrf保护,并在burp suite中使用intruder?

Django navigator.sendbeacon csrf 保护

存储“记住我”cookie 和 CSRF 保护

使用 Grails Spring Security 进行 CSRF 保护