Angular JS授权 - 在加载页面之前检查用户角色

时间:2015-02-28 06:38:03

标签: javascript angularjs

我正在Angular JS中编写cms前端,我不知道在用户第一次加载应用程序时如何处理授权用户查看特定内容。当用户已经登录并且只是在页面之间导航时,我有工作解决方案。我是这样做的:

angular.module("myApp")
.run ($rootScope, AUTH_EVENTS, AuthServ) ->
    $rootScope.$on '$stateChangeStart', (event, next) ->
      if next.data
        authorizedRoles = next.data.authorizedRoles
        unless AuthServ.isAuthorized(authorizedRoles)
          event.preventDefault()
          if AuthServ.isAuthenticated()
            $rootScope.$broadcast(AUTH_EVENTS.notAuthorized)
          else
            $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated)  

当用户更改路由时,将触发AuthServ.isAuthorized(authorizedRoles)。

当用户登录时,我从服务器获取令牌和用户数据。令牌存储在本地存储器中,用户数据存储在内存中(在顶级控制器的范围内)。在用户数据中,我有关于他的角色的信息,因此我可以检查他是否有权查看特定内容。

现在让我们假设用户已登录并重新加载页面。我仍然有令牌,因为这是在localStorage但我丢失了用户数据(所以我不知道他的角色是什么)。在从服务器再次获取数据之前,我不想向用户显示任何内容。所以我的问题是如何解决这个问题?我应该在何时何地向服务器请求用户数据?

我认为解决方案可能是手动引导应用程序。我试着做这样的事情:

app = angular.module('myApp', [])

fetchData = ->
	injector = angular.injector(['ng'])
	$http = injector.get('$http')
	API_URI = injector.get('API_URI')
	$localStorage = injector.get('$localStorage')

	$http.get("#{API_URI}/users/me?token=#{$localStorage.token}")
		.success (data) ->
			app.constant('USER_DATA', data)

bootstrapApplication = ->
	angular.element(document).ready ->
		angular.bootstrap(document, ['myApp'])

fetchData().then(bootstrapApplication)

此代码的问题在于我无法访问$ localStorage服务和API_URI常量。我需要它们来获取令牌并动态更改URL(开发,生产)。

那么什么是最好的解决方案?也许将用户角色存储在本地存储中?

任何帮助都会表示赞赏,谢谢。

2 个答案:

答案 0 :(得分:2)

您可以在路线配置中使用Angular的解析。以下是我正在解决“用户”问题的示例。对于特定的路线。它必须在角度加载此路线之前解决。

app.config( [ '$routeProvider', '$locationProvider',
    function( $routeProvider, $locationProvider ) {

        $routeProvider
            .when('/somePath', {
                templateUrl: "someView.html",
                controller: "someController",
                resolve: {
                    user: function( authService ){
                        return authService.getUser();
                    }
                }
            }
        );

    }
]);

这是服务(在这种情况下是工厂)。我正在检查是否首先存在auth.user,因此不会对每个路由更改提出请求:

app.factory('authService', [ '$http', '$q',
    function( $http, $q ) {

        var pub = {};

        pub.user = null;

        pub.getUser = function() {

            var deferred = $q.defer();

            if( pub.user ) {
                deferred.resolve( pub.user );
            }

            else{
                $http.get('/someAuthUrl').then(function( user ) {
                    pub.user = user;
                    deferred.resolve( user );
                });
            }

            return deferred.promise;

        };

        return pub;

    }
]);

最后是控制器,直到auth功能解析后才会加载所需的用户数据。您现在可以通过注入访问用户对象。

app.controller( 'someController', [ '$scope', 'user',
    function( $scope, user ) {

        //Controller runs here only when user is resolved.
        // Anything resolved will be passed in as your last dependency.
        $scope.user = user;

    }
]);

在这种情况下,您可以将服务注入控制器,并使用我们知道的authService.user。

app.controller( 'someController', [ '$scope', 'authService',
    function( $scope, authService ) {

        $scope.user = authService.user;

    }
]);

答案 1 :(得分:0)

这是因为每当您重新加载/导航时,都会创建新的控制器实例,并且您的控制器中的用户数据将丢失。最好的方法是将验证和存储数据的逻辑移动到服务并在控制器中使用该服务,这样您就不会丢失刷新/导航数据