Django csrf token + Angularjs

时间:2013-08-09 22:13:29

标签: javascript python django angularjs

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

是否存在从服务器设置令牌而不将{% csrf token %}作为模板的一部分(因为这些页面不通过django)?

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

5 个答案:

答案 0 :(得分:110)

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

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

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

对于Angular,它期望名为XSRF-TOKEN的cookie并且将使用X-XSRF-TOKEN标头执行POST / PUT / DELETE请求,因此您需要进行一些调整以使两者相互依赖:

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

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

就是这样。

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

更新

由于角度应用程序不是由django提供的,为了让cookie被设置,有角度的app需要首先对django进行GET请求。

答案 1 :(得分:60)

var foo = angular.module('foo', ['bar']);

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

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

答案 2 :(得分:11)

搜索后,对我有用的是this post,代码如下:

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的默认选项的内容,除了this pull request之外没有在我撰写这篇文章时为我工作。

答案 3 :(得分:1)

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

请在此处查看我关于AngularJS Single Page Web Application on Sub-domain A talking to a Django JSON (REST) API on Sub-domain B using CORS and CSRF protection

的回答

答案 4 :(得分:0)

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

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

在您的角度应用中,添加以下内容:

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

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

注意:由于每个请求上的CSRF令牌发生变化,因此目前在Django 1.10或更高版本中不起作用。见Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY