Django csrf 令牌 + Angularjs

IT技术 javascript python django angularjs
2021-01-29 19:00:33

我在使用 mod_wsgi 的 apache 服务器上运行 django,以及由 apache 直接提供服务的 angularjs 应用程序,而不是 django。我想对 django 服务器(运行 rest_framework)进行 POST 调用,但是我遇到了 csrf 令牌的问题。

有没有办法从服务器设置令牌而不将其{% csrf token %}作为模板的一部分(因为这些页面没有通过 django)?

  1. 我希望能够通过 GET 请求作为 cookie 获取 csrf 令牌。
  2. 我希望能够使用 csrf 令牌 cookie 值向 django 服务器发出 POST 请求。
5个回答

Django 和 AngularJS 都已经有 CSRF 支持,你的部分很简单。

首先,您需要在 Django 中启用 CSRF,我相信您已经这样做了,如果没有,请遵循 Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax

现在,Django 将设置一个以csrftoken第一个 GET 请求命名的 cookie ,并期望X-CSRFToken在以后的 POST/PUT/DELETE 请求中使用自定义 HTTP 标头

对于 Angular,它需要命名的 cookie 并将XSRF-TOKEN使用X-XSRF-TOKEN标头执行 POST/PUT/DELETE 请求,因此您需要做一些调整以使两者相互配合:

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

在你的 js 代码的某处添加上面两行,module.config() 块是一个很好的地方。

而已。

注意:这是针对 angular 1.1.5,旧版本可能需要不同的方法。

更新:

由于 angular 应用程序不是由 django 提供的,为了让 cookie 被设置,angular 应用程序需要先向 django 发出 GET 请求。

@dan-klasson 你是对的,他的 angular 应用程序不是由 Django 提供的。
2021-03-26 19:00:33
他仍然需要以某种方式设置cookie。
2021-03-30 19:00:33
@Preom 仅供参考,xsrfCookieName并且xsrfHeaderName在 angular 1.2 之后记录。
2021-04-04 19:00:33
对于 csrf 的解释,我给了你 +1 分,因为它让我走上了正确的道路。不幸的是,这对我不起作用,我在官方文档中找不到对xsrfCookieNAme的参考xsrfHeaderName不过还是谢谢你。
2021-04-05 19:00:33
我在登录/ api 中获取了 Set-Cookie 标头,它是 POST。我应该何时调用 GET 请求以及如何调用?
2021-04-09 19:00:33
var foo = angular.module('foo', ['bar']);

foo.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

使用 $http 的所有module服务和控制器将发送带有 csrf 令牌的请求。

这有效。只是让任何阅读这篇文章的人都知道......真的很棒的帖子。
2021-03-16 19:00:33
如下所示,这需要 AngularJS 1.1.5 或更高版本。
2021-03-21 19:00:33

四处搜索后,对我有用的是这篇文章,其中包含以下代码:

angular.module( '[your module name]',
    ... [some dependencies] ...
    'ngCookies',
    ... [other dependencies] ...
)
.run( function run( $http, $cookies ){

    // For CSRF token compatibility with Django
    $http.defaults.headers.post['X-CSRFToken'] = $cookies.get('csrftoken');
})

这当然是在通过 django 服务器的 GET 请求获取 cookie 之后。

我还查看了这里的其他一些答案,包括 Ye Liun 的,但在官方文档中找不到任何指定更改 $httpProvider 上 xsrf 的默认选项的内容,除了这个在我写这篇文章的时间。

我通过调用解决了不确定的问题$cookiesProvider.$get() ,生成一个新的本地$cookiesdocument.cookies,然后更新上的CSRF值$http默认值。我通过可耻地创建对$cookiesProvider:的全局引用来做到这一点的var cookiesProvider_ref = null; app.config( function($cookiesProvider) {cookiesProvider_ref = $cookiesProvider });然后cookiesProvider_ref我在我的登录success()回调中使用$http再次设置csrf 令牌标头字段。
2021-03-13 19:00:33
我发现以这种方式做事有问题。当我模仿是第一次实地考察中铬与ctrl+ shift+ n$cookies['csrftoken'];undefined因为这一行被执行的时候我还没有发送的任何请求我的Django的服务器。我先做一个OPTIONS请求,然后设置$http.defaults.headers.post['X-CSRFToken']全局,因为它$cookies.csrftoken是有效的。
2021-04-07 19:00:33
我最终不得不只使用getCookieDjango 站点推荐函数,因为我更喜欢这样做,而不是在 cookie 已经发送时包含到服务器的毫无意义的额外旅行。docs.djangoproject.com/en/dev/ref/csrf/#ajax
2021-04-10 19:00:33

我为我的 AngularJS 应用程序创建了一个 Django 应用程序,与我的(REST)API Django 应用程序在同一个 Django 项目中,它只提供 index.html 文件(它只是一个 sym.link)。通过这种方式,CSRF Coo​​kie 的设置无需额外的 GET 请求。

请在此处查看我关于子域 A 上的 AngularJS 单页 Web 应用程序使用 CORS 和 CSRF 保护与子域 B 上的 Django JSON (REST) API 交谈的答案

如果您将 cookie 设置为禁止 javascript 访问,则需要执行以下操作。在您的模板中,在创建 django 应用程序之前,添加以下内容:

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

在您的 angular 应用程序中,添加以下内容:

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

至少通过 Django 1.9,CSRF 令牌不会随着每个请求而改变。它仅在用户登录时更改。如果您正在开发单页 angular 应用程序,您需要确保在登录/注销时重置令牌,这应该可以正常工作。

注意:由于每次请求都会更改 CSRF 令牌,因此目前这在 Django 1.10 或更高版本中不起作用。请参阅使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular