如何在ui.router状态上设置路由过滤器?

时间:2015-07-12 07:21:22

标签: angularjs angular-ui-router

在Laravel中,设置路由过滤器非常简单。我们使用beforeFilter([])并指定控制器中的哪些函数可以在身份验证时访问,并且在特殊情况下也可以except

现在,我刚刚开始使用Angular的ui.router,状态的概念肯定是前进的方向,但我在这里问一个noob问题。如何在我的州上设置路由过滤器。我绝对不想使用resolve在各个路线上进行此操作。

这里有一些代码。这是我用于个人资料路线的内容。我使用resolve来确保只有在经过身份验证时才能访问它。但问题是,当我登录时,我的登录和注册路由仍然可以访问。他们不应该。它应该只是重定向到家。

现在我可以将解决方案添加到我登录时不想访问的状态,但这是正确的方法吗?如果有很多怎么办?这将重复代码。是否有“ui.router”方式来做到这一点?

.state('profile', {
                url: '/profile',
                templateUrl: 'js/app/partials/profile.html',
                controller: 'ProfileCtrl',
                resolve: {
                    authenticated: function($q, $location, $auth) {
                        var deferred = $q.defer();

                        if (!$auth.isAuthenticated()) {
                            $location.path('/login');
                        } else {
                            deferred.resolve();
                        }

                        return deferred.promise;
                    }
                }
            })

1 个答案:

答案 0 :(得分:2)

我认为一种方法是创建一个进行验证的服务,然后在运行块中,您可以在K.Toress提到的任何$stateChangeStart事件上调用该服务。

例如,如果要指定需要进行身份验证的状态,可以使用状态定义配置中的数据选项来定义是否需要进行身份验证。因此,要定义需要身份验证的状态,您可以尝试类似......

$stateProvider
  .state('foo', {

    templateUrl: 'foo.html',

    // etc...

    data: {
        requiresAuth: true
    } 

  });

然后,您可以在$stateChangeStart事件中检查此事件,该事件会传递toState参数,您可以从该参数访问data属性。

var app = angular.module('foo', ['ui.router'])

.factory('RouteValidator', ['$rootScope', '$auth', function($rootScope){

  return {
    init: init
  };

  function init(){
      $rootScope.$on('$stateChangeStart', _onStateChangeStart);
  }

  function _onStateChangeStart(event, toState, toParams, fromState, fromParams){


    // check the data property (if there is one) defined on your state 
    // object using the toState param

    var toStateRequiresAuth = _requiresAuth(toState),

        // if user is not authenticated and the state he is trying to access
        // requires auth then redirect to login page

        if(!$auth.isAuthenticated() && toStateRequiresAuth){
            event.preventDefault();
            $state.go('login');
            return;
        }

  }

  function _requiresAuth(toState){
        if(angular.isUndefined(toState.data) || !toState.data.requiresAuth){
            return false;
        }
        return toState.data.requiresAuth;
    }

}])

.run(['RouteValidator', function(RouteValidator){
  // inject service here and call init()
  // this is so that you keep your run blocks clean 
  // and because it's easier to test the logic in a service than in a 
  // run block
  RouteValidator.init();
}]);

修改

好的,我已经在plunker上做了一个非常基本的DEMO,希望能够展示这个概念。我也会在这里发布代码。帮助这有帮助。

<强> app.js

var app = angular.module('plunker', ['ui.router']);

app.config(['$stateProvider', function($stateProvider){

  $stateProvider

    .state('public', {
      url: "/public",
      templateUrl: "public.html"
    })

    .state('login', {
      url: "/login",
      templateUrl: "login.html",
      controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
      }
    })

    .state('admin', {

      url: "/admin",
      templateUrl: "admin.html",

      data: {
        requiresAuth: true
      },

      controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
      }

    });

}]);

app.factory('User', [function(){
  return {
    isAuthenticated: false
  };
}]);

app.factory('RouteValidator', ['$rootScope', 'User', '$state', function($rootScope, User, $state){

  return {
    init: init
  };
  /////////////////////////////////

  function init(){
      $rootScope.$on('$stateChangeStart', _onStateChangeStart);
  }

  function _onStateChangeStart(event, toState, toParams, fromState, fromParams){

     var toStateRequiresAuth = _requiresAuth(toState);

    if(!User.isAuthenticated && toStateRequiresAuth){
        event.preventDefault();
        $state.go('public');
        alert('You are not authorised to see this view');

        return;
    }

  }

  function _requiresAuth(toState){
      if(angular.isUndefined(toState.data) || !toState.data.requiresAuth){
          return false;
      }
      return toState.data.requiresAuth;
  }

}]);

app.run(['RouteValidator', function(RouteValidator){
  RouteValidator.init();
}]);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});

<强>的index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script>
    <script data-require="ui-router@0.2.15" data-semver="0.2.15" src="//rawgit.com/angular-ui/ui-router/0.2.15/release/angular-ui-router.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">

    <a ui-sref="public">public</a>
    <a ui-sref="login">login</a>
    <a ui-sref="admin">admin</a>
    <div ui-view></div>

  </body>

</html>