角度路由异步授权

时间:2015-10-08 12:50:02

标签: angularjs routing authorization

Angular没有提供任何路由授权/访问权限(我说的是默认的Angular route 1.x而不是beta 2.0或UI路由)。但我必须实施它。

我遇到的问题是我有一个服务,它调用服务器来提供此信息并返回一个承诺。然而,这些数据只获得一次,然后缓存在客户端上,但仍需要获取一次。

我现在想处理$routeChangeStart事件,检查下一个路由是否定义了特定属性authorize: someRole。然后,此处理程序应使用我之前提到的服务获取该数据,并相应地对返回的数据采取行动。

除了将解析添加到我的所有路线旁边的任何想法?我能以某种方式集中做到这一点吗?适用于所有适用的路线?

最终解决方案

在接受的答案的帮助下,我能够实现一个相当简单的集中式解决方案来执行异步授权。 Click here要查看它的实际效果或检查其内部工作代码。

4 个答案:

答案 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和讨论中打开一个问题