Angular没有提供任何路由授权/访问权限(我说的是默认的Angular route 1.x而不是beta 2.0或UI路由)。但我必须实施它。
我遇到的问题是我有一个服务,它调用服务器来提供此信息并返回一个承诺。然而,这些数据只获得一次,然后缓存在客户端上,但仍需要获取一次。
我现在想处理$routeChangeStart
事件,检查下一个路由是否定义了特定属性authorize: someRole
。然后,此处理程序应使用我之前提到的服务获取该数据,并相应地对返回的数据采取行动。
除了将解析添加到我的所有路线旁边的任何想法?我能以某种方式集中做到这一点吗?适用于所有适用的路线?
在接受的答案的帮助下,我能够实现一个相当简单的集中式解决方案来执行异步授权。 Click here要查看它的实际效果或检查其内部工作代码。
答案 0 :(得分:5)
最简单的方法是处理当前路由的解析依赖关系,而$routeChangeStart
是管理它的好地方。 Here's an example
app.run(function ($rootScope, $location) {
var unrestricted = ['', '/login'];
$rootScope.$on('$routeChangeStart', function (e, to) {
if (unrestricted.indexOf(to.originalPath) >= 0)
return;
to.resolve = to.resolve || {};
// can be overridden by route definition
to.resolve.auth = to.resolve.auth || 'authService';
});
$rootScope.$on('$routeChangeError', function (e, to, from, reason) {
if (reason.noAuth) {
// 'to' path and params should be passed to login as well
$location.path('/login');
}
});
});
另一种选择是将default
方法添加到$routeProvider
并修补$routeProvider.when
以从默认对象扩展路由定义。
答案 1 :(得分:1)
ui-router有很多你可以轻松操控的事件。我总是使用它。
State Change Events拥有您需要的一切。这样的东西将在AngularJS 2.x中实现。
但是,如果你正在寻找原生Angular 1.x.y路由器的解决方案,这个解决方案将无法帮助你。遗憾
答案 2 :(得分:1)
如果你可以使用ui-router,你可以这样做:
.state('root', {
url: '',
abstract: true,
templateUrl: 'some-template.html',
resolve: {
user: ['Auth', function (Auth) {
return Auth.resolveUser();
}]
}
})
Auth.resolveUser()
只是加载当前用户的后端调用。它返回一个promise,因此路由将在更改前等待加载。
该路由是抽象的,因此其他控制器必须从中继承以便工作,并且您具有额外的好处,即所有子控制器都可以通过解析访问当前用户。
现在您抓住了$stateChangeStart
中的app.run()
事件:
$rootScope.$on('$stateChangeStart', function (event, next) {
if (!Auth.signedIn()) { //this operates on the already loaded user
//user not authenticated
// all controllers need authentication unless otherwise specified
if (!next.data || !next.data.anonymous) {
event.preventDefault();
$state.go('account.login');
}
}else{
//authenticated
// next.data.roles - this is a custom property on a route.
if(!Auth.hasRequiredRole(next.data.roles)){
event.preventDefault();
$state.go('account.my'); //or whatever
}
}
});
然后需要角色的路线可能如下所示:
.state('root.dashboard', {
//it's a child of the *root* route
url: '/dashboard',
data: {
roles: ['manager', 'admin']
}
...
});
希望它有意义。
答案 3 :(得分:0)
我多次接触过这个问题,我还开发了一个模块(github)。 我的模块(构建在ui.router之上)基于$ stateChangeStart(ui.router事件),但概念与默认的ng.route模块相同,它只是一种不同的实现方式。 / p>
总之,我认为处理路由更改事件不是执行身份验证检查的好方法: 例如,当我们需要通过ajax获取acl时,事件无法帮助我们。
我认为,一个好方法可能是自动为每个受保护的"状态...
不幸的是,ui.Router没有提供拦截状态创建的API,所以我在$ stateProvider.state方法的基础上开始了我的模块返工。
最后,我正在寻找不同的意见,以便找到在AngularJS中实施身份验证服务的正确方法。
如果有人对此研究感兴趣...请在我的github和讨论中打开一个问题