ui router onEnter中的访问范围或服务以检查访问权限(auth)

joe*_*iks 27 angularjs angular-ui-router

好的,所以我有一个url"/ securepage"的状态,每当用户试图访问它时我都需要检查它.所以我读到有一个我可以使用的onEnter功能.但我似乎无法抓住范围,也不能从那里获得服务.我究竟做错了什么?

        .state('securepage', {
            url: "/securepage",
            template: securepage.html,
            onEnter: function(){
                // if (!$scope.main.isAuthenticated) $state.go("/login");
                // if (!myLoginService.currentUser()) $state.go("/login");
Run Code Online (Sandbox Code Playgroud)

我认为当前的选项是使用解析和/或检查控制器中的身份验证.但是不能将auth检查更好地放在onEnter上吗?

Joe*_*e H 15

我今天遇到了类似的问题.花了一整天时间,最后提出了一个可行的解决方案,而不是已经建议的解决方案.

我的主要目标是找到有选择地保护某些特定网页的简单有效方法.需要在加载或调用HTML或任何相关控制器之前执行安全检查.如果检查失败,则页面可以转发到其他地方而没有来自其他控制器的任何副作用.

我尝试了其他建议的方法.每个人都有自己的问题:

  1. 使用OnEnter:

    • 在进行异步调用以进行安全检查时,无法阻止ui-router继续进行状态转换.
  2. 使用$ rootScope.$ on('$ stateChangeStart'):

    • 对安全性检查的状态的管理将与$ stateProvider.state()定义分开.理想情况下,我宁愿在一个地方看到关于状态定义的所有内容.虽然这不是一个表明,但它并不理想.
    • 更大的问题是没有为页面的初始加载调用$ stateChangeStart事件.这是一个显示.

我的解决方案是使用resolve函数来定义一个promise,它将导致视图控制器在调用之前等待延迟完成.这项工作非常适合阻止控制器以异步方式启动.

这是我使用的代码的大致轮廓:

.config(['$stateProvider', function ($stateProvider) {
    // Handler for Restricting Access to a page using the state.resolve call
    var accessRestrictionHandler = function($q, $rootScope, $state) {
            var deferred = $q.defer();

            // make sure user is logged in
            asyncCheckForLogin(function(status) {
                if (status != "Logged In") {
                    // You may save target page URL in cookie for use after login successful later
                    // To get the relative target URL, it is equal to ("#" + this.url).  
                    //      The "this" here is the current scope for the parent state structure of the resolve call.
                    $state.go("loginPage");
                }
                else    // if logged in, continue to load the controllers.  Controllers should not start till resolve() is called.
                    deferred.resolve();
            }.bind(this));

            return deferred.promise;
        };


    $stateProvider
        .state('userProfile', {
            url: '/userProfile',
            views: {
                'main': {
                    templateUrl: 'userProfile.html',
                    controller: 'userProfileCtrl'
                }
            },

            // SIMPLY add the line below to all states that you want to secure
            resolve: { loginRequired : accessRestrictionHandler } 
        })

        .state(.... some other state)
        .state(.... some other state);

}]);
Run Code Online (Sandbox Code Playgroud)

我希望这会帮助你们中的一些人.


Phi*_*mas 14

另一种方法是让服务/控制器监听"$ stateChangeStart"事件.在那里,您可以检查被叫状态是否需要身份验证并重新路由请求.这是一个片段:

$rootScope.$on('$stateChangeStart', function (event, nextState, currentState) {
    if (!isAuthenticated(nextState)) {
        console.debug('Could not change route! Not authenticated!');
        $rootScope.$broadcast('$stateChangeError');
        event.preventDefault();
        $state.go('login');
    }
});
Run Code Online (Sandbox Code Playgroud)

isAuthenticated可以保留对您的服务的调用,检查nextState.data与身份验证相关的属性等.

  • 直接通过url访问状态时不会触发. (3认同)

Phi*_*mas 7

从他们的github页面查看此问题示例.它应该给你一些线索.