Javascript Django csrf令牌+;安格拉斯
我使用mod_wsgi在apache服务器上运行django,还有一个angularjs应用程序直接由apache而不是django提供服务。我想对django服务器(运行rest_框架)进行POST调用,但我对csrf令牌有问题 是否有某种方法可以在不将Javascript Django csrf令牌+;安格拉斯,javascript,python,django,angularjs,Javascript,Python,Django,Angularjs,我使用mod_wsgi在apache服务器上运行django,还有一个angularjs应用程序直接由apache而不是django提供服务。我想对django服务器(运行rest_框架)进行POST调用,但我对csrf令牌有问题 是否有某种方法可以在不将{%csrf token%}作为模板的一部分的情况下从服务器设置令牌(因为这些页面不经过django) 我希望能够通过get请求以cookie的形式获取csrf令牌 然后,我希望能够使用csrf令牌cookie值向django服务器发出POST
{%csrf token%}
作为模板的一部分的情况下从服务器设置令牌(因为这些页面不经过django)
Django和AngularJS都已经有了CSRF支持,您的部分非常简单 首先,您需要在Django中启用CSRF,我相信您已经这样做了,如果没有,请遵循Django文档 现在,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()块就是一个很好的地方
就这样
注意:这是针对angular 1.1.5的,旧版本可能需要不同的方法
更新:
由于angular应用程序不由django提供服务,为了设置cookie,angular应用程序需要首先向django发出GET请求。搜索后,对我有效的是以下代码:
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之后
我也在这里查看了一些其他答案,包括叶柳的答案,但在官方文档中找不到任何关于更改$httpProvider上xsrf默认选项的内容,除了在我写这篇文章时对我不起作用之外
var foo = angular.module('foo', ['bar']);
foo.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
使用$http的所有模块、服务和控制器都将使用csrf令牌发送请求。我为我的AngularJS应用程序创建了一个Django应用程序,它与我的(REST)API Django应用程序位于同一个Django项目中,只提供index.html文件(只是一个sym.link)。通过这种方式,CSRF Cookie的设置不需要额外的GET请求
请参阅我在这里关于的回答。如果您的cookie设置为不允许javascript访问,则需要执行以下操作。在模板中,在创建django应用程序之前,添加以下内容:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
至少通过Django 1.9,CSRF令牌不会随着每个请求而改变。它仅在用户登录时更改。如果您正在使用单页angular应用程序,您需要确保在登录/注销时重置令牌,这应该可以正常工作
注意:在Django 1.10或更高版本中,由于CSRF令牌在每个请求中都会发生更改,因此这目前不起作用。看到你在Django视图中发出的POST呼叫了吗?或者来自同一个域,使用另一个框架?@dan klasson后者,同一个域没有框架,请阅读以下指南:他仍然需要以某种方式设置cookie。@dan klasson你是对的,他的angular应用程序不是由Django提供的。我在csrf上给了你+1的解释,因为它让我走上了正确的道路。不幸的是,这对我不起作用,我在官方文档中找不到对
xsrfCookieNAme
和xsrfHeaderName
的引用。不过,谢谢。@Preom FYI,xsrfCookieName
和xsrfHeaderName
都是在angular 1.2之后记录的。我正在登录/api中获取设置的Cookie头,这是POST。我应该在什么时候调用GET请求以及如何调用?如下所示,这需要AngularJS 1.1.5或更高版本。这很有效。只是让任何读过这篇文章的人知道。。。非常棒的帖子。我发现这样做有问题。当我在chrome中使用ctrl
+shift
+n
,$cookies['csrftoken']模拟首次访问站点时代码>未定义,因为在执行该行时,我没有向django服务器发送任何请求。我首先执行一个OPTIONS
请求,然后全局设置$http.defaults.headers.post['X-CSRFToken']
,因为$cookies.CSRFToken
是有效的。我通过调用$cookiesProvider.$get()解决了未定义的问题
从文档生成新的本地$cookies
。cookies
然后更新$http
默认值上的csrf值。为此,我羞愧地创建了一个对$cookiesProvider
的全局引用:var cookiesProvider\u ref=null;config(函数($cookiesProvider){cookiesProvider\u ref=$cookiesProvider})代码>。然后在登录success()中使用cookiesProvider\u ref
callback以再次设置$http
csrf令牌头字段。我最终不得不使用Django网站推荐的getCookie
函数,因为我更喜欢这样做,而不是在cookie已经发送下来的情况下对服务器进行无意义的额外访问。
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]);