最简单的AngularJS应用程序与DRF的会话身份验证

时间:2017-03-22 02:02:43

标签: angularjs django authentication django-rest-framework session-cookies

我一直在敲打墙头太长时间试图使用基本的Django REST Framework设置在AngularJS中使用会话身份验证。我已经通过博客阅读了几十个堆栈溢出的问题和答案,我只是没有得到它。我有一个大型应用程序,我正在努力,但为了促进这个问题的答案,我已经在一个简单的Django REST框架教程代码{{3}的叉子上生成了一个极简主义的AngularJS应用程序。 }。 (所有前端依赖项都包含在fork中。)只需执行pip install -r requires.txtpython manage.py makemigrations snippetspython manage.py migrate,然后python manage.py runserver

感兴趣的主要代码在这里:

"use strict";

var geoint = angular.module('snippets', [
  'ngRoute',
  'ngCookies',
  'ngAnimate',
  'ngResource',
  'snippets.controllers',
])

.config(function ($routeProvider, $httpProvider) {
  $httpProvider.defaults.withCredentials = true;
  $httpProvider.defaults.xsrfCookieName = 'csrftoken';
  $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

  $routeProvider
    .when('/', {
      title:'Snippets - Home',
      templateUrl: STATIC_URL + 'snippets/partials/snippets.html',
      controller: 'SnippetsCtrl'
    })
    .otherwise({
      redirectTo: '/'
    });
})

.run(function($rootScope, $location, $http) {

    // Get a CSRF Token
    $http.get('api/auth/login/?next=/api/').then(
      function successCallback(response){
        console.log(response);
        // Post should come back with Set-Cookie sessionid, but it doesn't!
        $http.post('api/auth/login/', {username:'username', password:'password'}).then(
          function successCallback(response){
            console.log(response);
            // Get this user's information
            $http.get('api/currentuser/').then(
              function successCallback(response){
                console.log(response);
              })
          })
      },
      function errorCallback(response){
        alert(response);
      }
    );

});
<!DOCTYPE html>
<html lang="en" ng-app="pc2">
    {% load static from staticfiles %}
    <head>
        <meta charset="UTF-8">
        <title ng-bind="title">PC2</title>
        <script>var STATIC_URL = "{% static "" %}";</script>
        <link rel="stylesheet" type="text/css" href="{% static "resources/css/complete.min.css" %}">
        {% if debug %}
        <script src="{% static "resources/js/_bower.js" %}"></script>
        <script src="{% static "resources/js/app.js" %}"></script>
        <script src="{% static "resources/js/controllers.js" %}"></script>
        <script src="{% static "resources/js/directives.js" %}"></script>
        <script src="{% static "resources/js/filters.js" %}"></script>
        <script src="{% static "resources/js/services.js" %}"></script>
        {% else %}
        <script src="{% static "resources/js/complete.min.js" %}"></script>
        {% endif %}
    </head>

    <body>
        {% load static from staticfiles %}
        <div ng-include="'{% static "resources/partials/navbar.html" %}'"></div>
        <div ng-view class="container-fluid main-view"></div>
    </body>
</html>

我的嵌套GET和POST很难看,显然不是我在应用程序中真正做到这一点。但我认为应该可以工作,但事实并非如此。我一直在使用邮递员和铬来解决问题。问题的根源似乎是当我使用AngularJS时,POST不会返回包含sessionid的Set-Cookie。 (当我使用浏览器时。)因此,当它试图获取用户信息时,它没有设置cookie,并且它作为AnonymousUser进入Django。任何人都可以提供的帮助非常感谢!

所以问题是为什么这不适用于AngularJS,但它适用于浏览器?我也很感激最佳实践的输入,或更好的方法来解决这个问题。 (新的DRF端点,使用$ resource等)?

1 个答案:

答案 0 :(得分:0)

好的,今天早上更多地摆弄这个问题后,我得到了答案。对于DRF默认api登录视图,数据必须作为表单提交。因此,这最终成为解决方案:

.run(function($rootScope, $location, $http) {
$http.get('api/auth/login/').then(function successCallback(response){
console.log(response);
$http({
    "method": "POST",
    "url": 'api/auth/login/',
    "data": $.param({username:'username', password:'password', next:'/api/currentuser'}),
    "headers": {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(
  function successCallback(response){
    console.log(response);
  })})

});

我仍然非常有兴趣学习这种“正确”的方法。我应该构建一个单独的DRF登录视图吗?我应该使用Angular $资源而不是$ http调用吗?我会很感激任何和所有的投入。