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

Angular JS authorization - check user role before loading the page

本文关键字:检查 用户 角色 授权 JS 加载 Angular      更新时间:2023-09-26

我正在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(开发、生产)。

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

任何帮助都将不胜感激,谢谢。

您可以在路由配置中使用Angular的解析。下面是一个我解析特定路由的"用户"的示例。它必须在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;
    }
]);

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