尝试访问受保护的页面时,尝试登录需要工作

时间:2017-08-03 17:09:08

标签: angularjs django django-rest-framework jwt

  • Django 1.11
  • Django REST Framework(DRF)3.6
  • DRF-JWT 1.10
  • AngularJS 1.6.5
  • ui-router 1.0.3

所有这项技术都相当崭新,并且已经连续几天搞乱了这个问题。通过以下类和存储库了解了这个堆栈(减去我刚刚切换到一周前的UI路由器):

https://www.udemy.com/django-angularjs/learn/v4/overview

https://github.com/codingforentrepreneurs/Django-AngularJS/tree/master/src

这些目录可能与我的问题最相关:

Config和JS:https://github.com/codingforentrepreneurs/Django-AngularJS/tree/master/src/static/js/app

需要登录的拦截器:https://github.com/codingforentrepreneurs/Django-AngularJS/tree/master/src/static/js/app/core/interceptors

服务,需要登录的页面和拦截器:https://github.com/codingforentrepreneurs/Django-AngularJS/tree/master/src/static/js/app/core/comment

我正在尝试为我的项目调整它。

我已经阅读了几篇纯粹为此目的使用ui-router的教程,但他们似乎没有使用DRF-JWT或者缺少像我这样的新手需要的重要步骤。

无论如何,我有两个网址:

/

/dashboard

前者是登录,/dashboard需要授权,如果此人没有登录,则应该路由到/。在我开始尝试实现此操作之前,可以输入{ {1}}未经过身份验证并查看。我已经验证当一个人通过DRF-JWT登录令牌时,它正在生成并写入cookie,因为我可以在成功登录时/dashboard

由于我一直在努力实现这一点,我甚至无法加载console.log。我收到了/个问题,无法解决。

代码时间:

我改变后得到$injector:modulerr

$injector:modulerr

// dashboard.module.js

angular.module('dashboard', ['chart.js']);

其他势在必行的JS:

// dashboard.module.js

angular.module('dashboard', ['chart.js', 'interceptors']);

-

// login_required.service.js

'use strict';

angular.
    module('interceptors').
        factory('LoginRequiredInterceptor', function($cookies, $location) {
            return function(response) {
                console.log('working')
                console.log('interceptor error')
                console.log(response)
                if (response.status == 401){
                    var currentPath = $location.path();
                    console.log(currentPath)
                    if (currentPath == '/') {
                        $location.path('/')
                    } else {
                        $location.path('/').search('next', currentPath)
                    }
                }
            }
        })

-

// interceptors.module.js

'use strict';

angular.module('interceptors', ['ngCookies']);

真的没有从我从上面克隆的项目中更新以下内容:

// dashboard.component.js

'use strict';

angular.module('dashboard').
    component('dashboard', {
        templateUrl: '/api/templates/dashboard.html',
        controller: function($cookies, $location, $stateParams, $rootScope, $scope) {
             // Nothing at this point
        }
    });

最后,主配置:

// dashboard.service.js

'use strict';

angular.
    module('dashboard').
        factory('Dashboard', function(LoginRequiredInterceptor, $cookies, $httpParamSerializer, $location, $resource){

            var token = $cookies.get("token")
            if (token){
                commentCreate["headers"] = {"Authorization": "JWT " + token}
                commentDelete["headers"] = {"Authorization": "JWT " + token}
                commentUpdate["headers"] = {"Authorization": "JWT " + token}
            }

            return $resource(url, {}, {
                query: commentQuery,
                get: commentGet,
                create: commentCreate,
                delete: commentDelete,
                update: commentUpdate,
            })

        });

此外,// app.config.js 'use strict'; angular.module('app'). config( function( $locationProvider, $resourceProvider, $stateProvider, $urlRouterProvider, $authProvider ) { // Enable HTML5 mode $locationProvider.html5Mode({ enabled:true }) // Remove trailing slashes to avoid API issues $resourceProvider.defaults.stripTrailingSlashes = false; // Route handling if the URL does not match any of the below // it will send the user to the login screen $urlRouterProvider.otherwise('/'); $stateProvider // The top URL (app/) is the login screen .state('/', { url: '/', views: { 'content@': { component: 'login' } } }) // Logout and reroute to the login screen .state('logout', { redirectTo: '/' }) // After successful login, the user is brought to the dashboard // Parent of the states below it .state('dashboard', { url: '/dashboard', views: { 'content@': { component: 'dashboard' } }, }) // Test State1 .state('dashboard.test1', { views: { 'dashboard@dashboard': { template: '<p style="position: absolute;top: 110%; left: 50%">Test1</p>' } } }) // Test State2 .state('dashboard.test2', { views: { 'dashboard@dashboard': { template: '<p style="position: absolute;top: 50%; left: 50%">Test2</p>' } } }) }); 我正在阅读(位于<scripts>标记的底部):

<body>

如果有任何其他方法有帮助,请告诉我。

1 个答案:

答案 0 :(得分:0)

好吧,我找到了一个似乎对我有用的解决方案,而且相当简单。它可能存在一些问题,因此非常感谢有关为何不这样做的反馈。

我几乎放弃了拦截器,服务等。

同样,我实际上只有2个网址:'/''/dashboard'。前者是登录,后者是用户可用的所有工具(最终有几十个工具),但它们将是父dashboard的子视图。你可以在这里看到这个:

// app.config.js

'use strict';

angular.module('app').
    config(
        function(
            $locationProvider,
            $resourceProvider,
            $stateProvider,
            $urlRouterProvider,
            $authProvider
            ) {

            // Enable HTML5 mode
            $locationProvider.html5Mode({
                enabled:true
            })

            // Remove trailing slashes to avoid API issues
            $resourceProvider.defaults.stripTrailingSlashes = false;

            // Route handling if the URL does not match any of the below
            // it will send the user to the login screen
            $urlRouterProvider.otherwise('/');

            $stateProvider
                // The top URL (app/) is the login screen
                .state('/', {
                    url: '/',
                    views: {
                        'content@': {
                            component: 'login'
                        }
                    }
                })

                // Logout and reroute to the login screen
                .state('logout', {
                    redirectTo: '/'
                })

                // After successful login, the user is brought to the dashboard
                // Parent of the states below it
                .state('dashboard', {
                    url: '/dashboard',
                    views: {
                        'content@': {
                            component: 'dashboard'
                        }
                    },
                })

                // Test child State1
                .state('dashboard.test1', {
                    views: {
                        'dashboard@dashboard': {
                            template: '<p style="position: absolute;top: 110%; left: 50%">Test1</p>'
                        }
                    }
                })

                // Test child State2
                .state('dashboard.test2', {
                    views: {
                        'dashboard@dashboard': {
                            template: '<p style="position: absolute;top: 50%; left: 50%">Test2</p>'
                        }
                    }
                })
    });

以下是将JWT令牌写入cookie的登录信息。

// login.component.js

'use strict';

angular.module('login').
    component('login', {
        templateUrl: 'api/templates/login.html',
        controller: function($cookies, $http, $location, $stateParams, $rootScope, $scope) {
            var loginUrl = 'api/users/login/'
            $scope.loginError = {}
            $scope.user = {}

            $scope.$watch(function() {
                if ($scope.user.password) {
                    $scope.loginError.password = ''
                } else if ($scope.user.username) {
                    $scope.loginError.username = ''
                }
            })

            var tokenExists = $cookies.get('token')
            if (tokenExists) {
                // verify token
                $scope.loggedIn = true;
                $cookies.remove('token')
                $scope.user = {
                    username: $cookies.get('username')
                }
                // window.location.reload()
            }

            // Main login handling for user
            $scope.doLogin = function(user) {
                // console.log(user)
                if (!user.username) {
                    $scope.loginError.username = ['This field may not be blank.']
                } 

                if (!user.password) {
                    $scope.loginError.password = ['This field is required.']
                }

                // If both the username and the password are supplied then POST it to the login API URL
                if (user.username && user.password) {
                    $http({
                        method: 'POST',
                        url: loginUrl, 
                        data: {
                            username: user.username,
                            password: user.password                            
                        },
                        headers: {}
                    }).then(function successCallback(r_data, r_status, r_headers, r_config) {
                        // console.log(r_data.data)
                        $cookies.put('token', r_data.data.token)
                        $cookies.put('username', r_data.data.username)
                        var token = $cookies.get('token')
                        // console.log(token)

                        $location.path('/dashboard')
                        // window.location.reload()                      
                    }, function errorCallback(e_data, e_status, e_headers, e_config) {
                        // Check if this is a 400 error which is related to an invalid password
                        if (e_data.status == 400) {
                            $scope.loginError.invalid = ['The credentials entered are invalid.']
                        }
                    })    
                } 
            }
        }
    })

然后,对于仪表板,我刚刚执行了以下操作:

// dashboard.component.js

'use strict';

angular.module('dashboard').
    component('dashboard', {
        templateUrl: '/api/templates/dashboard.html',
        controller: function($cookies, $location, $stateParams, $rootScope, $scope) {
            var token = $cookies.get('token')
            console.log(token)
            if (token) {
                $location.path('/dashboard')
            } else {
                $location.path('/')
            }
        }
    });

这似乎与我的期望相符:

  • 如果您尝试转到/dashboard,它会将您转到登录屏幕
  • 如果您登录并被路由到/dashboard,则可以在网址中输入/dashboard并显示
  • 如果您退出,则不允许您通过在浏览器中输入或点击后退按钮来查看/dashboard
  • 它不允许直接访问子视图,我认为这仅仅是由于路由:如果父视图不能,则无法呈现子视图。

无论如何,反馈将非常感激。

编辑:意识到这与我正在复制的项目有多么相似,但我在仪表板组件中没有拦截器。