2015-07-12 68 views
1

在Laravel中,設置路由過濾器非常簡單。我們使用beforeFilter([])並指定控制器中的哪些功能應在身份驗證時可訪問,並且在特殊情況下也有except如何在ui.router狀態設置路由過濾器?

現在,我剛開始使用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; 
        } 
       } 
      }) 
+0

你爲什麼不聽像'$ stateChangeStart'事件和你想在這裏做像'認證是什麼'。 –

+0

你能舉一個@ K.Toress的例子嗎? –

回答

2

我想一個辦法是創建請問您的驗證,然後在運行塊,你會調用該服務上的任何$stateChangeStart事件K.Toress提到的服務。

如果您想指定哪些狀態需要驗證,例如,您可以在狀態定義配置中使用數據選項來定義它是否需要驗證。因此,要在被傳遞一個toState參數,從中可以訪問data性質的$stateChangeStart事件定義需要身份驗證,你可以嘗試像的狀態......

$stateProvider 
    .state('foo', { 

    templateUrl: 'foo.html', 

    // etc... 

    data: { 
     requiresAuth: true 
    } 

    }); 

然後,您可以檢查。

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(); 
}]); 

編輯

好吧,我做了一個非常基本的DEMO上plunker,希望能展示的概念。我也會在這裏發佈代碼。幫助這個幫助。

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="[email protected]" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script> 
    <script data-require="[email protected]" 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> 
+0

感謝您的回答。有沒有這樣的內置ui路由器? –

+0

據我所知不是。 ui.router只是給你'$ stateChangeStart'事件,你可以使用它來實現你想要的。 –

+0

啊,這太遺憾了。你可以給我一個完整的例子來幫助我開始踢球。理想情況下,我希望提供一組我希望通過身份驗證的狀態以及一系列未經身份驗證的狀態,以便在登錄後訪問登錄頁面和註冊頁面時,您只需返回主頁。 –