【问题标题】:Simplest AngularJS App to with Session Authentication to DRF对 DRF 进行会话身份验证的最简单的 AngularJS 应用程序
【发布时间】:2017-08-13 23:07:50
【问题描述】:

长期以来,我一直在努力让会话身份验证在 AngularJS 中与基本的 Django REST 框架设置一起工作。我已经通过博客阅读了数十个堆栈溢出问题和答案,但我就是不明白。我有一个正在开发的大型应用程序,但为了帮助解决这个问题,我在基本的 Django REST 框架教程代码 here 的一个分支之上制作了一个极简主义的 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 很丑陋,显然我不会在应用程序中真正做到这一点。但我认为它应该工作,但它没有。我一直在使用邮递员和 chrome 来解决问题。问题的根源似乎是当我使用 AngularJS 时,POST 没有返回包含 sessionid 的 Set-Cookie。 (当我使用浏览器时,它会这样做。)因此,当它尝试获取用户信息时,它没有设置 cookie,并且它作为 AnonymousUser 进入 Django。非常感谢任何人提供的任何帮助!

所以问题是 为什么这在 AngularJS 中不起作用,但在浏览器中却起作用?我也希望能提供有关最佳实践或解决此问题的更好方法的意见。 (新的 DRF 端点,使用 $resource 等)?

【问题讨论】:

  • 您是否尝试过设置withCredentials 标志?参见例如developer.mozilla.org/en-US/docs/Web/HTTP/…
  • 我不完全确定这是否是您的问题,但我会看看您如何在 POST 请求中传递用户名/密码参数。尝试查看此线程以供参考:stackoverflow.com/questions/31572937/…
  • 您能否提供一个使用 angularjs 登录的示例?我克隆了存储库,它似乎工作正常。
  • jonrsharpe,应该由$httpProvider.defaults.withCredentials = true; Linovia 处理。当您转到 localhost:8000 并查看控制台输出时,您应该看到“找不到用户”。问题是 app.js 文件中的最终 GET 请求未通过身份验证。所以我认为它行不通。请注意,如果您使用 admin 或使用浏览器的 api 手动登录,那么您将获得一个 sessionid cookie,然后 Angular 代码将成功。
  • 嗯,我只是想出了一些可以将问题推回的东西。问题是 POST 没有做我认为它正在做的事情。无论用户名和密码是什么,它都会得到一个 200 状态码(即使它们是错误的)。

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


【解决方案1】:

好吧,在今天早上更多地摆弄这个问题之后,我得到了答案。 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 $resource 而不是 $http 调用吗?我将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 2021-12-28
    • 2011-06-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 2011-10-12
    相关资源
    最近更新 更多