Python Django csrf 令牌 + Angularjs
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18156452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django csrf token + Angularjs
提问by Preom
I have django running on an apache server using mod_wsgi, as well as an angularjs app served directly by apache, not by django. I would like to make POST calls to the django server (running rest_framework) but I am having problems with the csrf token.
我在使用 mod_wsgi 的 apache 服务器上运行 django,以及由 apache 直接提供服务的 angularjs 应用程序,而不是 django。我想对 django 服务器(运行 rest_framework)进行 POST 调用,但是我遇到了 csrf 令牌的问题。
Is there someway to set the token from the server without putting {% csrf token %}
as part of the template (since these pages aren't going through django)?
有没有办法从服务器设置令牌而不将其{% csrf token %}
作为模板的一部分(因为这些页面没有通过 django)?
- I would like to be able to get a csrf token through a GET request as a cookie.
- I would like to be able to then make POST requests to the django server with the csrf token cookie value.
- 我希望能够通过 GET 请求作为 cookie 获取 csrf 令牌。
- 我希望能够使用 csrf 令牌 cookie 值向 django 服务器发出 POST 请求。
采纳答案by Ye Liu
Django and AngularJS both have CSRF support already, your part is quite simple.
Django 和 AngularJS 都已经支持 CSRF,你的部分很简单。
First, you need to enable CSRF in Django, I believe you have already done so, if not, follow Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax.
首先,您需要在 Django 中启用 CSRF,我相信您已经这样做了,如果没有,请遵循 Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax。
Now, Django will set a cookie named csrftoken
on the first GET request and expects a custom HTTP header X-CSRFToken
on later POST/PUT/DELETE requests.
现在,Django 将设置一个以csrftoken
第一个 GET 请求命名的 cookie ,并期望X-CSRFToken
在以后的 POST/PUT/DELETE 请求中使用自定义 HTTP 标头。
For Angular, it expects the cookie named XSRF-TOKEN
and will do POST/PUT/DELETE requests with X-XSRF-TOKEN
header, so you need to do a little bit tweak to make the two go with each other:
对于 Angular,它需要命名的 cookie 并将XSRF-TOKEN
使用X-XSRF-TOKEN
标头执行 POST/PUT/DELETE 请求,因此您需要做一些调整以使两者相互配合:
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
Add above two lines somewhere in your js code, module.config() block is a good place for this.
在你的 js 代码的某处添加上面两行,module.config() 块是一个很好的地方。
That's it.
就是这样。
NOTE:This is for angular 1.1.5, older versions might need different approach.
注意:这是针对 angular 1.1.5,旧版本可能需要不同的方法。
Update:
更新:
Since the angular app isn't served by django, in order to let the cookie to be set, angular app needs to do a GET request to django first.
由于 angular 应用程序不是由 django 提供的,为了让 cookie 被设置,angular 应用程序需要先向 django 发出 GET 请求。
回答by Preom
After searching around, what worked for me was from this postwith the following code:
四处搜索后,对我有用的是这篇文章,其中包含以下代码:
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');
})
This is of course after getting the cookie through a GET request from the django server.
这当然是在通过 django 服务器的 GET 请求获取 cookie 之后。
I also looked into some of the other answers here, including Ye Liun's but couldn't find anything in the official docs specifying changes to the defaults options for xsrf on $httpProvider, other than this pull requestwhich didn't work for me at the time of me writing this post.
我还查看了这里的其他一些答案,包括 Ye Liun 的,但在官方文档中找不到任何指定更改 $httpProvider 上 xsrf 的默认选项的内容,除了这个在我写这篇文章的时间。
回答by Nikolay Baluk
var foo = angular.module('foo', ['bar']);
foo.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
And all modules services and controllers, where $http used, will send requests with csrf token.
使用 $http 的所有模块服务和控制器将发送带有 csrf 令牌的请求。
回答by Visionscaper
I created a Django App for my AngularJS app, in the same Django project as my (REST) API Django App, that only serves the index.html file (which is just a sym.link). In this way the CSRF Cookie is set without an additional GET request.
我为我的 AngularJS 应用程序创建了一个 Django 应用程序,在与我的(REST)API Django 应用程序相同的 Django 项目中,它只提供 index.html 文件(它只是一个 sym.link)。通过这种方式,CSRF Cookie 的设置无需额外的 GET 请求。
Please see my answer here about 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
请在此处查看我关于子域 A 上的 AngularJS 单页 Web 应用程序使用 CORS 和 CSRF 保护与子域 B 上的 Django JSON (REST) API 交谈的答案
回答by Zags
If you have your cookies set to disallow javascript access, you need to do the following. In your template, before creating the django app, add this:
如果您将 cookie 设置为禁止 javascript 访问,则需要执行以下操作。在您的模板中,在创建 django 应用程序之前,添加以下内容:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
In your angular app, add this:
在您的 angular 应用程序中,添加以下内容:
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]);
At least through Django 1.9, the CSRF token does not change with each request. It only changes when a user logs in. If you are doing a single page angular app, you need to make sure you reset the token on login/logout and this should work fine.
至少通过 Django 1.9,CSRF 令牌不会随着每个请求而改变。它仅在用户登录时更改。如果您正在执行单页 angular 应用程序,则需要确保在登录/注销时重置令牌,这应该可以正常工作。
NOTE: This does not currently work in Django 1.10 or later due to the CSRF token changing on each request. See Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY
注意:由于每次请求都会更改 CSRF 令牌,因此这在 Django 1.10 或更高版本中目前不起作用。请参阅使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular