繁体   English   中英

Django csrf token + Angularjs

[英]Django csrf token + 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请求。

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,它期望cookie名为XSRF-TOKEN ,并将使用X-XSRF-TOKEN标头执行POST / PUT / DELETE请求,因此您需要进行一些调整以使两者相互依赖:

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

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

而已。

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

更新:

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

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

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

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

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

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的默认选项的内容,除了这个拉取请求对我不起作用我写这篇文章的时间。

我为我的AngularJS应用程序创建了一个Django应用程序,与我的(REST)API Django App在同一个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>

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

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

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

注意:由于每个请求上的CSRF令牌发生变化,因此目前在Django 1.10或更高版本中不起作用。 请参阅使用CSRF_COOKIE_HTTPONLY将Django CSRF令牌传递给Angular

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM