使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular

Posted

技术标签:

【中文标题】使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular【英文标题】:Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY 【发布时间】:2017-04-12 14:22:10 【问题描述】:

在 Django 中,当 CSRF_COOKIE_HTTPONLY 设置为 True 时,CSRF cookie 获得 httponly 标志,这从安全角度来看是可取的,但打破了将此 cookie 添加到 httpProvider 的标准角度解决方案,如下所示:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

通过 Django 1.9,有一种解决方法,您可以通过将 cookie 放入模板中直接将其传递给应用程序:

<script>
    window.csrf_token = " csrf_token ";
</script>

并将其放入 Angular 应用程序中:

angularApp.config(["$httpProvider", function($httpProvider) 
    $httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
]

不幸的是,这不适用于 Django 1.10+ 中的单页 Angular 应用程序,因为 CSRF cookie 在每次请求后都会更改。在 CSRF_COOKIE_HTTPONLY 设置开启的情况下,如何从 Angular 向 Django 1.10+ 发出发布请求?注意:禁用 CSRF 保护不是一个可接受的答案。

【问题讨论】:

【参考方案1】:

我认为这个问题在这次讨论中得到了很好的回答。

https://groups.google.com/forum/#!topic/django-developers/nXjfLd8ba5k

https://code.djangoproject.com/ticket/27534

CSRF_COOKIE_HTTPONLY 不为单页应用程序提供任何额外的安全性。有人推荐这个解决方案

var csrftoken = getCookie('csrftoken');
if (csrftoken === null) 
    csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
    if (csrftoken === null) 
        console.log('No csrf token');
    

但是,或者如果您正在为您的应用程序公开 csrftoken,没有什么能阻止恶意用户获取并使用它。如果您正在运行单页应用程序,您不妨设置 CSRF_COOKIE_HTTPONLY=False,根据下面的评论:

加文·瓦尔 2015 年 5 月 4 日

怎么会?你不能只从不同的域 ajax-fetch 东西。

我说的是单个域。在页面上注入 javascript 不包含 CSRF 令牌可以在同一个页面上获取不同的页面 域来获取它。

如果您已经将 javascript 注入到受害者页面 (XSS),则无需获取 CSRF 令牌,您已经获得了更大的控制权。

嗯,HttpOnly 标志旨在减少攻击者的损害 一旦已经可以注入javascript就可以做到。但我同意——隐藏 来自 javascript 的 CSRF 令牌不会以任何方式增加安全性, 但文档暗示确实如此。我想在 说明此设置没有任何意义的文档。

如果您仍然认为那里有有效的攻击向量,请将其发送至 secu...@djangoproject.com 并添加更多说明。

没有攻击向量。这只是误导 文档。

【讨论】:

总结一下:“你不能。不要使用 CSRF_COOKIE_HTTPONLY 设置”

以上是关于使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用dplyr将特定的数据列移动到最前面使用dplyr将特定数据列移动到另一指定数据列的后面使用dplyr将特定数据列移动到另一指定数据列的前面

您将如何将 node.js 子进程与 discord.js 一起使用?

使用 ATL 编译 dll,将方法参数作为接口,但将它们作为 coclasses

使用 Tumbleweed 安全文件传输将文件发送到 S3

使用 VBA 将表单另存为报表

使用 jQuery 1.5 将请求作为 jsonp 发送,将响应解释为文本