如何在值解决之前防止状态更改

时间:2015-01-25 01:21:10

标签: angularjs authorization angular-ui-router

我设置了身份验证,我希望阻止任何路由/状态加载,直到我知道用户有权访问该页面。如果是,则应加载请求的页面,如果没有,则应该进入登录页面。

我的配置功能:

$stateProvider

    .state('login', {
        url: '/login',
        templateUrl : 'login.html',
        controller  : 'loginController',
        data: {
            authorizedRoles: [USER_ROLES.guest]
        }
    })

    .state('home', {
        url: '/',
        templateUrl : 'home.html',
        controller  : 'homeController',
        data: {
            authorizedRoles: [USER_ROLES.admin]
        }
    })

    .state('admin', {
        url: '/admin',
        templateUrl : 'admin.html',
        controller  : 'adminController',
        data: {
            authorizedRoles: [USER_ROLES.admin]
        }
    });

$urlRouterProvider.otherwise('/login');

$locationProvider.html5Mode(true);

我的跑步功能:

$rootScope.$on('$stateChangeStart', function(event, next) {

    event.preventDefault();

    function checkAuthorization() {
        if(!AuthService.isAuthorized(authRole)) {
            $state.go('login');
        } else {
            $state.go(next.name);
        }
    }

    if(AuthService.getRoleId() === undefined) {
        // We'll have to send request to server to see if user is logged in
        AuthService.checkLogin().then(function(response) {
            checkAuthorization();
        });
    } else {
        checkAuthorization();
    }
})

如果我将event.preventDefault()保留在我的运行功能中,则应用程序将停留在始终进入请求状态的循环中。如果我删除event.preventDefault()语句,那么应用程序将加载视图(在一秒钟内可见),然后才意识到不允许用户查看它(然后转到正确的状态)。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

您应该使用resolve并向服务器发出请求,以查看用户是否已登录解析

https://github.com/angular-ui/ui-router/wiki#resolve

.state('whatever',{
...
 promiseObj:  function($http){
            // $http returns a promise for the url data
            return $http({method: 'GET', url: '/someUrl'}).$promise;
         },
...
}

OR

如果您在控制器中拨打电话,请在解决状态下进行呼叫,如果您没有登录,您的api应该使用401响应,如果您有拦截服务,则重定向到登录屏幕。

答案 1 :(得分:0)

详细说明如何在此Q & A with working plunker中执行此类解析/等待。

Auth服务的提取版本是:

.factory('userService', function ($timeout, $q) {

    var user = undefined;

    return {
        // async way how to load user from Server API
        getAuthObject: function () {
            var deferred = $q.defer();

            // later we can use this quick way -
            // - once user is already loaded
            if (user) {
                return $q.when(user);
            }

            // server fake call, in action would be $http
            $timeout(function () {
                // server returned UN authenticated user
                user = {isAuthenticated: false };
                // here resolved after 500ms
                deferred.resolve(user)
            }, 500)

            return deferred.promise;
        },

        // sync, quick way how to check IS authenticated...
        isAuthenticated: function () {
            return user !== undefined
                && user.isAuthenticated;
        }
    };    
})

最重要的部分是

  1. var user = undefined; - " global"变量是
    • 包含用户,如果他有权利则可以回答
    • 不包含用户(尚未),答案是"未授权"然后
  2. 返回服务功能:isAuthenticated
  3. 那应该解决这个问题。查看更多详情here