角UI路由器登录认证 [英] angular ui-router login authentication

查看:188
本文介绍了角UI路由器登录认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来AngularJS,我有点困惑的我怎么能在以下情况下使用anguler的UI路由器。

I am new to AngularJS, and I'm little confused of how can I use anguler-ui-router in the following scenario.

我建立一个Web应用程序由两部分组成,首先是与它的网页的登录立即登记和看法,第二个是仪表盘(登录后成功)。

I'm building a web application consists of two sections, first is the homepage with it's login and signup views, and the second is the dashboard (after login successful).

我的index.html与棱角分明的应用程序和UI路由器配置来处理'/登录和/注册的意见家里部分创建
并有与它的应用程序和UI路由器配置仪表板部分要处理很多次意见另一个文件dashboard.html

I've created index.html for the home section with its angular app and ui-router config to handle '/login' and '/signup' views and there is another file dashboard.html for the dashboard section with its app and ui-router config to handle many sub views

现在我完成了仪表板部分,不知道如何将两个部分具有各自不同的角度应用结合起来。我怎么能告诉家里应用重定向到仪表板应用程序?

now I finished the dashboard section and don't know how to combine the two sections with their different angular apps. how could I tell the home app to redirect to the dashboard app?

推荐答案

我在做一个更好的演示,以及清理一些服务为可用模块的过程,但这里是我想出什么用。这是一个复杂的过程来解决一些注意事项,所以挂在那里。你需要打破这种分解成数块。

I'm in the process of making a nicer demo as well as cleaning up some of these services into a usable module, but here's what I've come up with. This is a complex process to work around some caveats, so hang in there. You'll need to break this down into several pieces.

看看这个普拉克

首先,你需要一个服务来存储用户的身份。我称之为主要。它可以进行检查,以查看用户是否已登录,并在请求时,它可以解决一个对象,该重presents有关用户身份的基本信息。这可能是你需要什么,但(这是否适用于你的应用程序)的要领将是一个显示名称,用户名,可能是一个电子邮件,并且用户所属的角色。校长也有方法来做角色检查。

First, you need a service to store the user's identity. I call this principal. It can be checked to see if the user is logged in, and upon request, it can resolve an object that represents the essential information about the user's identity. This can be whatever you need, but the essentials would be a display name, a username, possibly an email, and the roles a user belongs to (if this applies to your app). Principal also has methods to do role checks.

.factory('principal', ['$q', '$http', '$timeout',
  function($q, $http, $timeout) {
    var _identity = undefined,
      _authenticated = false;

    return {
      isIdentityResolved: function() {
        return angular.isDefined(_identity);
      },
      isAuthenticated: function() {
        return _authenticated;
      },
      isInRole: function(role) {
        if (!_authenticated || !_identity.roles) return false;

        return _identity.roles.indexOf(role) != -1;
      },
      isInAnyRole: function(roles) {
        if (!_authenticated || !_identity.roles) return false;

        for (var i = 0; i < roles.length; i++) {
          if (this.isInRole(roles[i])) return true;
        }

        return false;
      },
      authenticate: function(identity) {
        _identity = identity;
        _authenticated = identity != null;
      },
      identity: function(force) {
        var deferred = $q.defer();

        if (force === true) _identity = undefined;

        // check and see if we have retrieved the identity data from the server. if we have, reuse it by immediately resolving
        if (angular.isDefined(_identity)) {
          deferred.resolve(_identity);

          return deferred.promise;
        }

        // otherwise, retrieve the identity data from the server, update the identity object, and then resolve.
        //                   $http.get('/svc/account/identity', { ignoreErrors: true })
        //                        .success(function(data) {
        //                            _identity = data;
        //                            _authenticated = true;
        //                            deferred.resolve(_identity);
        //                        })
        //                        .error(function () {
        //                            _identity = null;
        //                            _authenticated = false;
        //                            deferred.resolve(_identity);
        //                        });

        // for the sake of the demo, fake the lookup by using a timeout to create a valid
        // fake identity. in reality,  you'll want something more like the $http request
        // commented out above. in this example, we fake looking up to find the user is
        // not logged in
        var self = this;
        $timeout(function() {
          self.authenticate(null);
          deferred.resolve(_identity);
        }, 1000);

        return deferred.promise;
      }
    };
  }
])

其次,你需要检查用户想去状态的服务,确保他们登录(如果需要的话,不进行登录,密码重置等必要的),然后做一个角色检查(如果你的应用程序需要这一点)。如果他们没有通过认证,将它们发送到登录页面。如果他们进行身份验证,但不能一个角色检查,并将它们发送到拒绝访问的页面。我把这种服务授权

.factory('authorization', ['$rootScope', '$state', 'principal',
  function($rootScope, $state, principal) {
    return {
      authorize: function() {
        return principal.identity()
          .then(function() {
            var isAuthenticated = principal.isAuthenticated();

            if ($rootScope.toState.data.roles && $rootScope.toState.data.roles.length > 0 && !principal.isInAnyRole($rootScope.toState.data.roles)) {
              if (isAuthenticated) $state.go('accessdenied'); // user is signed in but not authorized for desired state
              else {
                // user is not authenticated. stow the state they wanted before you
                // send them to the signin state, so you can return them when you're done
                $rootScope.returnToState = $rootScope.toState;
                $rootScope.returnToStateParams = $rootScope.toStateParams;

                // now, send them to the signin state so they can log in
                $state.go('signin');
              }
            }
          });
      }
    };
  }
])

现在,所有你需要做的是在听 UI-路由器的 $ stateChangeStart 。这给你一个机会,可以查看当前的状态,他们希望去,并插入您授权检查的状态。如果失败,你可以取消航线过渡,或更改为不同的路线。

Now all you need to do is listen in on ui-router's $stateChangeStart. This gives you a chance to examine the current state, the state they want to go to, and insert your authorization check. If it fails, you can cancel the route transition, or change to a different route.

.run(['$rootScope', '$state', '$stateParams', 'authorization', 'principal',
    function($rootScope, $state, $stateParams, authorization, principal) {
      $rootScope.$on('$stateChangeStart', function(event, toState, toStateParams) {
        // track the state the user wants to go to; authorization service needs this
        $rootScope.toState = toState;
        $rootScope.toStateParams = toStateParams;
        // if the principal is resolved, do an authorization check immediately. otherwise,
        // it'll be done when the state it resolved.
        if (principal.isIdentityResolved()) authorization.authorize();
      });
    }
  ]);

有关跟踪用户的身份棘手的部分是寻找它,如果你已经通过身份验证(比如,你是一个previous会议结束后访问该页面,并在cookie中保存的身份验证令牌,或者你硬刷新页面,或跌落到从URL的链接)。因为这样 UI路由器的作品,你需要做你的身份一旦决心,你的AUTH前检查。您可以使用决心选项在您的状态配置做到这一点。我对所有国家继承的网站,这迫使主要别的发生之前需要解决一个父状态。

The tricky part about tracking a user's identity is looking it up if you've already authenticated (say, you're visiting the page after a previous session, and saved an auth token in a cookie, or maybe you hard refreshed a page, or dropped onto a URL from a link). Because of the way ui-router works, you need to do your identity resolve once, before your auth checks. You can do this using the resolve option in your state config. I have one parent state for the site that all states inherit from, which forces the principal to be resolved before anything else happens.

$stateProvider.state('site', {
  'abstract': true,
  resolve: {
    authorize: ['authorization',
      function(authorization) {
        return authorization.authorize();
      }
    ]
  },
  template: '<div ui-view />'
})

这里有一个问题... 决心只被调用一次。一旦你的身份查找承诺完成后,它将不会再次运行的决心委托。因此,我们必须做你的权威性检查在两个地方:一旦根据你的身份承诺在解析解析,它涵盖了第一次你的应用程序负载,并曾在 $ stateChangeStart 如果分辨率已经完成,覆盖在你身边的状态浏览任意时间。

There's another problem here... resolve only gets called once. Once your promise for identity lookup completes, it won't run the resolve delegate again. So we have to do your auth checks in two places: once pursuant to your identity promise resolving in resolve, which covers the first time your app loads, and once in $stateChangeStart if the resolution has been done, which covers any time you navigate around states.

好了,你有什么到目前为止我们做了什么?

OK, so what have we done so far?


  1. 我们检查时,如果用户登录的应用程序加载。

  2. 我们跟踪有关登录用户的信息。

  3. 我们重定向它们在国家签署要求用户先登录状态。

  4. 我们重定向到一个拒绝访问的状态,如果他们没有权限来访问它。

  5. 我们有一个机制,将用户重定向回他们要求,如果我们需要他们登录原来的状态。

  6. 我们可以出签一个用户(需要音乐会进行接线与任何客户端或服务器code,管理您的AUTH票)。

  7. 我们的的需要每次都向用户发送回到登录页面重新加载他们自己的浏览器或链接下降。

  1. We check to see when the app loads if the user is logged in.
  2. We track info about the logged in user.
  3. We redirect them to sign in state for states that require the user to be logged in.
  4. We redirect them to an access denied state if they do not have authorization to access it.
  5. We have a mechanism to redirect users back to the original state they requested, if we needed them to log in.
  6. We can sign a user out (needs to be wired up in concert with any client or server code that manages your auth ticket).
  7. We don't need to send users back to the sign-in page every time they reload their browser or drop on a link.

在哪里,我们何去何从?好了,你可以通过添加数据角色对这些国家(或他们的父母,如果你想使用继承)。在这里,我们限制资源以管理员:

Where do we go from here? Well, you can organize your states into regions that require sign in. You can require authenticated/authorized users by adding data with roles to these states (or a parent of them, if you want to use inheritance). Here, we restrict a resource to Admins:

.state('restricted', {
    parent: 'site',
    url: '/restricted',
    data: {
      roles: ['Admin']
    },
    views: {
      'content@': {
        templateUrl: 'restricted.html'
      }
    }
  })

现在,你可以控制的状态,由国家哪些用户可以访问的路线。任何其他问题?也许只改变基于他们是否被记录视图的一部分?没问题。使用 principal.isAuthenticated()甚至 principal.isInRole()与任何许多方法可以有条件地显示模板或一个元素

Now you can control state-by-state what users can access a route. Any other concerns? Maybe varying only part of a view based on whether or not they are logged in? No problem. Use the principal.isAuthenticated() or even principal.isInRole() with any of the numerous ways you can conditionally display a template or an element.

首先,注入主要到控制器或什么的,然后贴范围,使您可以在视图中方便地使用它:

First, inject principal into a controller or whatever, and stick it to the scope so you can use it easily in your view:

.scope('HomeCtrl', ['$scope', 'principal', function($scope, principal) {
  $scope.principal = principal;
});

显示或隐藏的元素:

Show or hide an element:

<div ng-show="principal.isAuthenticated()">
   I'm logged in
</div>
<div ng-hide="principal.isAuthenticated()">
  I'm not logged in
</div>

等,等等,等等。不管怎么说,在您的示例应用程序,你将有主页,它可以让未经授权的用户通过拖放的状态。他们可以链接到登录或注册国,或者有内置到该网页的形式。无论适合你。

Etc., so on, so forth. Anyways, in your example app, you would have a state for home page that would let unauthenticated users drop by. They could have links to the sign-in or sign-up states, or have those forms built into that page. Whatever suits you.

仪表板页面可以全部继承它要求用户在和,也就是说,是用户角色成员的身份登录的状态。所有我们已经讨论了授权的东西会流从那里。

The dashboard pages could all inherit from a state that requires the users to be logged in and, say, be a User role member. All the authorization stuff we've discussed would flow from there.

这篇关于角UI路由器登录认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆