在我的应用中,当用户登录时,我authService
设置了内部标记isAuthenticated
。现在,在每次路由更改时,我都会将监听器附加到$routeChangeStart
事件,该事件会检查authService.isAuthenticated()
。如果没有,它应该重定向到登录路由。
问题是当用户刷新页面时(所有authService
设置都丢失了)并且它再次返回登录状态(同时在服务器上仍然有有效的会话)。这不是我想要的。
我想做的是“阻止”路由更改,直到我获得用户身份验证的信息(来自authService
的即时消息,或者来自服务器,如果authService
中没有信息可用authService
1}},例如刷新后)。我在 // returns promise
currentUser: function() {
if (authService.isAuthenticated()) {
return $q.when(authService.loggedUser);
}
return $http.get('/session').then(function(response) {
authService.loggedUser = response.user;
return $q.when(authService.loggedUser);
});
}
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if(isRouteRestricted(next)) {
authService.currentUser().then(null, function() {
$location.path('/login');
});
}
});
并希望在事件监听器中使用它。
{{1}}
事情是它不能按预期工作。我仍然可以在很短的时间内看到目标路线,然后用户被重定向。我相信这是由于承诺的本质,但如何摆脱这种“眨眼”效应?
答案 0 :(得分:6)
我会在顶级控制器中执行类似的操作,这将是刷新页面时调用的第一个控制器(为js中的拼写错误道歉,我是一个coffeescript人):
var authCheck = function (event, next, current) {
if(isRouteRestricted(next)) {
authService.currentUser().then(null, function() {
$location.path('/login');
});
}
}
authCheck(null, populateNextSomehow).then(function () {
// all of your controller code, probably in a separate function
});
$rootScope.$on("$routeChangeStart", authCheck);
这将确保在authCheck完成之前无法调用控制器代码。
答案 1 :(得分:4)
为防止用户访问路由,您必须执行以下操作:
首先,设置路线并添加“访问”等属性:allowAnonymous:true或false
// in app.js
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);
myApp.config(function ($httpProvider, $routeProvider) {
window.routes = {
'/Login':
{ templateUrl: '/Account/Login',
controller: 'AccountController',
access : {allowAnonymous : true}
},
'/MembersPage':
{ templateUrl: '/Home/SomePage,
controller: SomePageController',
access: {allowAnonymous:false}
}
};
for (var path in window.routes) {
$routeProvider.when(path, window.routes[path]);
}
$routeProvider.otherwise({ redirectTo: '/Login' });
});
其次,您必须识别经过身份验证的用户:
有几种方法可以做到这一点,但我更喜欢在使用'服务'时使用AngularJS的强大功能。因此,我创建了一个'UserService',我们存储当前用户名和一个值 - 表明是否经过身份验证。
// in UserService.js
myApp.factory('userService', function () {
var user = {
isLogged: false,
username: '',
};
var reset = function() {
user.isLogged = false;
user.username = '';
};
return {
user: user,
reset : reset
};
});
最后,捕获路线会更改事件并相应地对待它们:
在我们提供服务后,是时候使用它并实现路由的检查功能。拦截路由更改事件有几种方法,但我们只对那些在用户重定向之前发生的方法感兴趣,因此我们可以检查是否经过身份验证:'$ routeChangeStart','$ locationChangeStart'。在这里,我们可以检查用户将要允许匿名访问的路由以及用户是否已登录。如果失败,我们可以显示错误消息并将用户重定向到登录页面。
// in RootController.js
myApp.controller('RootController',
function ($scope, $route, $routeParams, $location, $rootScope, authenticationService,
userService, toaster) {
$scope.user = userService.user;
$scope.$on('$routeChangeStart', function (e, next, current) {
if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) {
$location.path("/Login");
}
});
$scope.logout = function () {
authenticationService.logout()
.success(function (response) {
userService.reset();
toaster.pop("info", 'You are logged out.', '');
});
};
$rootScope.$on("$locationChangeStart", function (event, next, current) {
for (var i in window.routes) {
if (next.indexOf(i) != -1) {
if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) {
toaster.pop("error", 'You are not logged in!', '');
$location.path("/Login");
}
}
}
});
});
完整文章在这里:http://net-daylight.blogspot.ro/
希望它有所帮助!