我使用mod_wsgi在apache服务器上运行django,以及直接由apache服务的angularjs应用程序,而不是django。我想对django服务器进行POST调用(运行rest_framework),但我遇到了csrf令牌的问题。
是否存在从服务器设置令牌而不将{% csrf token %}
作为模板的一部分(因为这些页面不通过django)?
答案 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 Cookie的设置没有额外的GET请求。
的回答答案 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