我希望通过外部服务为我的路由创建一个简单的身份验证检查。
我定义了路由对象的访问要求:
$routeProvider
.when('/', {
templateUrl: 'src/app/views/index.html',
controller: 'indexCtrl',
authenticated: true
})
.when('/login', {
templateUrl: 'src/app/views/login.html',
controller: 'loginCtrl',
anonymous: true
})
.otherwise({
redirectTo: '/'
})
;
然后,我检查我是否在$routeChangeStart
事件中具有权限。
$rootScope.$on('$routeChangeStart', function (event, next) {
if(next.authenticated && !$myService.isLoggedin())
$location.path("/login");
else if(next.anonymous && $myService.isLoggedin())
$location.path("/secured");
});
实际上,它有效-
如果用户未经过身份验证,则会将他移动到登录页面,如果他经过身份验证,但路由仅适用于匿名用户,则会将其移动到另一个页面,等等。
但是 - 这种重定向实际上是在加载控制器和模板之后发生的!它会导致我的控制器对我的 REST API 执行一些不必要的请求,即使我没有经过身份验证。
在他们处理之前,我该如何处理路线?
使用$routeProvider解析
.when('/', {
templateUrl: 'src/app/views/index.html',
controller: 'indexCtrl',
resolve: function($q, $location) {
var deferred = $q.defer();
deferred.resolve();
if (!isAuthenticated) {
$location.path('/login');
}
return deferred.promise;
}
})
我的解决方案是将$locationChangeStart
和$routeChangeStart
结合起来:
$rootScope.$on('$locationChangeStart', function (event) {
//If login data not available, make sure we request for it
if($facebook.isConnected()==null) {
$facebook.getLoginStatus();
event.preventDefault();
return;
}
var next=parseRoute().$$route;
if(!Auth.loginCheck(next))
event.preventDefault();
});
我从angular-route.js
复制了parseRoute()
来解析要路由的给定 URL。
然后我构建我的登录检查处理程序(Auth.loginCheck
),如果它失败,它返回 false。
我还使用 $routeChangeStart
来处理$route.reload()
事件,所以现在在我的身份验证状态中每次更改后,我只执行$route.reload()
:
$rootScope.$on('$routeChangeStart', function (event, next) {
Auth.loginCheck(next);
});
最后,我只是确保此自定义服务始终使用简单的run()
方法运行。
编辑:
我们现在使用 ngAuth,这是我们设计用于解决该确切问题的模块(基于我之前给出的答案)。
最后,我们开发了一个角度模块来解决这个问题。本模块基于我之前在这里发布的答案。
由于这里的请求,我们发布了一个现在可以运行的测试版:http://github.com/GoDisco/ngAuth
随意使用它。
Angularjs resolve example:
.when('/profile', {
templateUrl: 'views/profile.html',
controller: 'ProfileCtrl',
resolve: {
app: function($q, $rootScope, $location) {
var defer = $q.defer();
if ($rootScope.currentUser == undefined) {
$location.path('/login');
};
defer.resolve();
return defer.promise;
}
}
尝试使用路由resolve
属性。它会在加载任何控制器或模板之前解析传递给它的所有函数/依赖项。如果依赖项返回承诺,则在解决之前不会加载任何内容。
尝试在解析中传递身份验证服务,并在身份验证失败时重定向。
请看一看-> https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw
$stateProvider下面使用$routeProvider。此维基将为您提供更多见解。https://github.com/angular-ui/ui-router/wiki#resolve
Angular-http-auth 允许您在 HTTP 级别(获取模板时)非常优雅地处理授权,并在需要时提示登录。如果授权被拒绝,所有这些甚至无需加载模板(或控制器)。显然是我迄今为止见过的最好的事情。
https://github.com/witoldsz/angular-http-auth