我今天遇到了类似的问题。花了一整天的时间,终于想出了一个可行的解决方案,而不是这里已经建议的解决方案。
我的主要目标是找到简单有效的方法来选择性地保护某些特定网页。需要在加载或调用 HTML 或任何相关控制器之前执行安全检查。如果检查失败,页面可能会被转发到其他地方,而不会受到其他控制器的任何副作用。
我尝试了其他建议的方法。每个人都有自己的一系列问题:
使用 OnEnter:
- 在进行异步调用以进行安全检查时,无法阻止 ui-router 继续状态转换。
使用 $rootScope.$on('$stateChangeStart'):
- 需要安全检查的状态的管理将与 $stateProvider.state() 定义分开。理想情况下,我宁愿在一个地方看到关于状态定义的所有内容。虽然这不是一个炫耀,但它并不理想。
- 一个更大的问题是没有调用 $stateChangeStart 事件来进行页面的初始加载。这是一个展示者。
我的解决方案是使用一个解析函数来定义一个承诺,这将导致视图控制器在调用它们之前等待延迟完成。这非常适合阻止控制器以异步方式启动。
这是我使用的代码的粗略轮廓:
.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);
}]);
我希望这会对你们中的一些人有所帮助。