在Angular中授权检查访问权限

时间:2016-04-15 21:37:26

标签: javascript angularjs http xmlhttprequest angular-http-interceptors

我正在使用git拍摄的Angular网络应用模板。我无法理解一个函数,我想,验证用户是否拥有授权。不是吗?我的目标是拥有一个登录功能。获取响应并保存令牌。然后,当$ state更改时,检查是否仍有令牌。我能怎么做?这是代码:

core.js:

'use strict'; 

angular.module('app.core').controller('App', ['config', '$scope', '$state', '$rootScope', 'shortHistory','session', '$window', 'authorize', function(config, $scope, $state, $rootScope, shortHistory, session, $window, 'authorize') {

var vm = this;

vm.title = config.appTitle;

$scope.app = config;
$scope.$state = $state;
vm.currentUser = null;

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
  authorize.checkAccess(event, toState, toParams);
});

$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
  $('body').toggleClass('nav-shown', false);
});

$rootScope.$on('$userSet', function(event, user) {
  vm.currentUser = user;
  $window.localStorage.setItem('token', vm.currentUser.token);
});

shortHistory.init($scope);

}]);

common.js:

(function() {
'use strict';

angular.module('app.common')
  .service('shortHistory', shortHistory)
  .service('session', session)
 // .service('authorize', authorize)
  .service('authenticationService', authenticationService);

shortHistory.$inject = ['$state'];
function shortHistory($state) {
  var history = this;

  function setItem(what, state, params) {
    history[what] = {
      state: state,
      params: params
    };
  }

  this.init = function(scope) {
    scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){
      setItem('from', fromState, fromParams);
      setItem('to', toState, toParams);
    });
  };

  this.goTo = function(where) {
    $state.go(history[where].state.name, history[where].params)
  };
}

session.$inject = ['$http', '$q', '$rootScope'];
function session($http, $q, $rootScope) {
  var session = this;

  this.fetchCurrentUser = function(url) {
    var userFetch;
    if (session.getCurrentUser()) {
      userFetch = $q(function(resolve) {
        resolve(session.getCurrentUser());
      });
    } else {
      userFetch = $http.get(url);
    }
    return userFetch;
  };

  this.getCurrentUser = function() {
    return this.user;
  };

  this.setCurrentUser = function(user) {
    this.user = user;
    $rootScope.$broadcast('$userSet', this.user);
  };
}
/* THIS IS THE CODE THAT I'VE NOT TOUCHED, IT WAS IN THE TEMPLATE
authorize.$inject = ['session', '$state', '$urlRouter', '$rootScope'];
function authorize(session, $state, $rootScope) {
  this.checkAccess = function(event, toState, toParams) {
    if (!session.getCurrentUser() && !(toState.data && toState.data.noAuth)) {
      event.preventDefault();
      session.fetchCurrentUser('api/sers')
        .success(function(user) {
          session.setCurrentUser(user);
          $state.go(toState.name, toParams);
        })
        .error(function() {
          $state.go('login');
        });
      }
  };
}
*/
authenticationService.$inject = ['$http', '$rootScope', 'session', '$state'];
function authenticationService($http, $rootScope, session) {
  var vm = this;
  vm.loginError = '';
  this.login = function(user) {
    var userData = {
      email: user.email,
      password: user.password
    }
    return $http.post('api/login/', userData)
      .success(function(data) {
        var loggedUser = jQuery.extend(data, userData);
        session.setCurrentUser(loggedUser);
        $rootScope.$broadcast('$userLoggedIn');
      });
  };

  var token = localStorage.getItem('token');

  this.logout = function() {
    return $http.post('api/logout/', token)
      .success(function(data) {
        session.setCurrentUser(null);
        $rootScope.$broadcast('$userLoggedOut');
      });
  }
}

})();

Auth.js:

 (function() {
 'use strict';

 angular.module('app.profile')
  .controller('LoginController', loginController)
  .run(runAuth);

loginController.$inject = ['authenticationService'];
function loginController(
  authenticationService
  ) {
  var vm = this;
  vm.user = {};
  vm.loginError = '';

  this.login = function() {
    authenticationService.login(vm.user)
      .then(null, function(err) {
        vm.loginError = err.data.result;
      });
  };
}

runAuth.$inject = ['$rootScope', '$state', 'authenticationService'];
function runAuth($rootScope, $state, authenticationService) {
  $rootScope.logout = authenticationService.logout;
  $rootScope.$on('$userLoggedIn', function() {
    $state.go('app.dashboard');
  });
  $rootScope.$on('$userLoggedOut', function() {
    $state.go('login');
  });
}
})();

profile.module.js:

'use strict';

angular.module('app.profile',['ui.router'])

.config(['$stateProvider', function($stateProvider) {
  $stateProvider
    .state('login', {
      url: '/login',
      data: {
        noAuth: true
      },
      templateUrl: 'app/modules/profile/auth/login.html',
      controller: 'LoginController',
      controllerAs: 'vm'
    })
    .state('app.profile', {
      url: '/profile',
      templateUrl: 'app/modules/profile/edit/edit.html',
      controller: 'ProfileController',
      controllerAs: 'vm'
    });
  }]);

原始项目是:https://github.com/flatlogic/angular-dashboard-seed 我无法理解该身份验证的工作原理以及在何处插入控制器以进行身份​​验证。例如,现在,我无法登录但无法进行注销,即使我没有令牌,我也可以正确地转到/ dashboard,或者只能由已登录用户查看的/ profile。

1 个答案:

答案 0 :(得分:0)

你在这里有相当多的代码,但我觉得你的问题可以在理论上得到更多的回答而不是更多的代码!

  • 使用后端服务器设置会话信息(通常是HTTP标头中的cookie),然后不要在AngularJS代码中进行任何本地操作。我看到你正在检查本地存储的一些区域。让后端将HTTP唯一标志设置为true并围绕不知道会话ID构建应用逻辑更容易,更安全
  • 利用拦截将401 ajax请求重定向到您的登录页面。这将允许您处理会话超时,未经授权的路由访问等实例。一个非常简单的处理程序,它将简单地重定向逻辑https://docs.angularjs.org/api/ng/service/ $ http#interceptors
  • 根据您的路由(您似乎正在使用UI路由器),您可以根据从身份验证服务返回的用户管理对特定路由的权限。我遇到的最干净的实现使用了UI路由器和嵌套状态。需要身份验证的状态具有配置的根“resolve”参数,该参数执行用户会话的验证(可能只是对受保护端点的简单HTTP GET以确定用户是否已经过身份验证)。当您需要了解任何给定控制器中的用户并且您始终可以知道您的用户服务已经找到了(并且不需要依赖广播)时,您将真正欣赏这种架构。

例如:

$stateProvider
  .state('rootProtected', {
    templateUrl: '/js/views/rootProtected.html',
    resolve: {
      data: function(coreuser) {
        return user.initialize();
      }
    }
  })
  .state('rootProtected.userProfile', {
    templateUrl: '/js/views/userProfile.html'
  })
  .state('public', {
    templateUrl: '/js/views/login.html'
  });
  • 尽量不要围绕会话管理创建太多的服务/工厂。我在整个互联网的教程中看到了这一点。真的,只需创建一个核心用户服务,记录用户,记录用户,验证用户,获取用户等。您将开始意识到许多数据是相互关联的,没有理由分散逻辑多项服务或广播活动。