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

Angularjs 如何在解析值之前防止状态更改,angularjs,authorization,angular-ui-router,Angularjs,Authorization,Angular Ui Router,我设置了身份验证,以防止加载任何路由/状态,直到我知道用户有权访问页面。如果是,则应加载请求的页面,如果不是,则应转到登录页面 我的配置功能: $stateProvider .state('login', { url: '/login', templateUrl : 'login.html', controller : 'loginController', data: { authorizedRo

我设置了身份验证,以防止加载任何路由/状态,直到我知道用户有权访问页面。如果是,则应加载请求的页面,如果不是,则应转到登录页面

我的配置功能:

$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();
    }
})
我的跑步功能:

$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();
    }
})
如果我在run函数中保留
event.preventDefault()
,那么应用程序将陷入一个始终处于请求状态的循环中。如果我删除
event.preventDefault()
语句,那么应用程序将在意识到不应允许用户查看视图(然后进入正确状态)之前加载视图(该视图将显示一秒钟)


如何解决此问题?

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


如果您在控制器中进行了调用,请在resolve in状态下进行调用,在该状态下,如果用户未登录,api应以401响应,如果您有拦截服务,则重定向到登录屏幕

本文详细解释了如何执行此类解决/等待操作

身份验证服务的提取版本为:

.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;
        }
    };    
})
最重要的部分在哪里

  • var user=未定义-“全局”变量,该变量为
    
    • 包含用户并可以回答他是否有权限
    • 不包含用户(尚未),答案为“未授权”
  • 返回的服务功能:
    isAuthenticated

  • 这应该可以解决问题。查看更多详细信息

    我已经对此进行了研究,这似乎是最好的解决方案,但是,我还没有听说过设置拦截。你能举例说明我如何实现你所解释的吗?@cornflakes24看看这个我在responseError中有一个开关,它检查rejection.status并根据它重定向到的某个位置的状态。400->登录401->登录所有其他错误页。@如果使用令牌身份验证,则返回24。拦截器是一种将令牌添加到服务器的每个请求中的好方法。谢谢!似乎即使设置了resolve,它也会开始从州控制器执行代码。我可以使用拦截器获取它,使其正确重定向到登录页面,但不是在从控制器执行一些我不希望执行的代码之后:/@cornflakes24对您必须添加的服务器进行调用。$promise so state等待调用完成,然后运行控制器代码