Javascript Django 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

我使用mod_wsgi在apache服务器上运行django,还有一个angularjs应用程序直接由apache而不是django提供服务。我想对django服务器(运行rest_框架)进行POST调用,但我对csrf令牌有问题

是否有某种方法可以在不将
{%csrf token%}
作为模板的一部分的情况下从服务器设置令牌(因为这些页面不经过django)

  • 我希望能够通过get请求以cookie的形式获取csrf令牌
  • 然后,我希望能够使用csrf令牌cookie值向django服务器发出POST请求

  • 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;
    }]);