当前位置: 首页 > 面试题库 >

AngularJS UI路由器登录身份验证

刘乐童
2023-03-14
问题内容

我是AngularJS的新手,在以下情况下我对如何使用angular-“ ui-router”感到有些困惑:

我正在构建一个包含两个部分的Web应用程序。第一部分是带有登录和注册视图的主页,第二部分是仪表板(成功登录后)。

index.html为home部分创建了一个带有角度应用程序和ui- router配置的,用于处理/login/signup查看,还有一个dashboard.html针对仪表板部分的文件,其应用程序和ui- router配置用于处理许多子视图。

现在,我完成了仪表板部分,并且不知道如何将这两个部分与不同的角度应用程序结合在一起。我如何告诉家用应用程序重定向到仪表板应用程序?


问题答案:

我正在做一个更好的演示,并将其中的一些服务清理到一个可用的模块中,但这是我想出的。要解决一些警告,这是一个复杂的过程,所以请坚持。您需要将其分解为几部分。

看看这个pl。

首先,您需要一项服务来存储用户的身份。我叫这个principal。可以检查它是否查看用户是否登录,并且可以根据请求解析一个代表有关用户身份的基本信息的对象。这可以是您需要的任何内容,但必不可少的是显示名称,用户名(可能是电子邮件)以及用户所属的角色(如果适用于您的应用程序)。Principal还具有进行角色检查的html" target="_blank">方法。

.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;
      }
    };
  }
])

其次,您需要一项服务来检查用户想要进入的状态,确保他们已登录(如果需要;登录,密码重置等不需要),然后进行角色检查(如果您的应用是需要这个)。如果未通过身份验证,请将其发送到登录页面。如果它们通过了身份验证,但未通过角色检查,请将其发送到拒绝访问页面。我称这项服务authorization

.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) {
                  // user is signed in but not
                  // authorized for desired state
                  $state.go('accessdenied');
              } else {
                // user is not authenticated. Stow
                // the state they wanted before you
                // send them to the sign-in 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-router$stateChangeStart。这使您有机会检查当前状态,他们想进入的状态并插入授权检查。如果失败,则可以取消路由转换,或更改为其他路由。

.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();
      });
    }
  ]);

跟踪用户身份的棘手部分是如果您已通过身份验证,则查找该身份(例如,您在上一个会话之后访问该页面,并将auth令牌保存在cookie中,或者您可能很难刷新页面,或者从链接拖放到URL上)。由于这种方式ui- router有效,因此您需要在身份验证之前完成一次身份解析。您可以使用resolve状态配置中的选项来执行此操作。对于所有状态都继承自该站点的站点,我有一个父状态,这会迫使主体在发生其他任何事情之前先进行解析。

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

这里还有另一个问题…
resolve只会被调用一次。一旦您完成对身份查询的承诺,就不会再运行解析委托。因此,我们必须在两个位置进行身份验证检查:一次是根据中的身份承诺解析resolve,这一次是应用程序首次加载;一次是$stateChangeStart在解决方案完成后,这一次遍历您浏览状态的时间。

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

  1. 如果用户已登录,我们将检查该应用何时加载。
  2. 我们跟踪有关登录用户的信息。
  3. 我们将它们重定向到需要用户登录的状态的登录状态。
  4. 如果他们无权访问它们,我们会将它们重定向到拒绝访问状态。
  5. 如果需要用户登录,我们有一种机制可以将用户重定向回他们请求的原始状态。
  6. 我们可以注销用户(需要与管理您的身份验证票的任何客户端或服务器代码保持一致)。
  7. 每当用户重新加载浏览器或断开链接时,我们 都不 需要将用户带回到登录页面。

我们从这里去哪里?嗯,你可以组织你的状态到需要的标志地区。您可以通过添加需要身份验证/授权用户dataroles这些国家(或他们的父母,如果你想使用继承)。在这里,我们将资源限制为管理员:

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

现在,您可以按状态控制哪些用户可以访问路由。还有其他问题吗?也许仅根据视图是否已登录来更改视图的一部分?没问题。可以使用,principal.isAuthenticated()甚至可以principal.isInRole()使用多种方式有条件地显示模板或元素。

首先,注入principal控制器或其他任何东西,并将其粘贴到示波器上,以便可以在视图中轻松使用它:

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

显示或隐藏元素:

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

等等,依此类推。无论如何,在示例应用程序中,您将拥有主页状态,该状态将使未经身份验证的用户掉队。他们可以具有指向登录或注册状态的链接,或者可以将那些表单内置到该页面中。任何适合您的。

仪表板页面都可以从要求用户登录并成为User角色成员的状态继承。我们已经讨论过的所有授权内容都将从那里流淌。



 类似资料:
  • 问题内容: 我有一个使用yeoman,grunt和bower创建的AngularJS应用程序。 我有一个登录页面,该页面具有用于检查身份验证的控制器。如果凭据正确,我将重新路由到主页。 app.js LoginControler.js 在主页上,我有 在中,检查登录信息,如果登录成功,则在服务工厂中设置用户对象。我不知道这是否正确。 我需要的是,当用户登录时,它会在用户对象中设置一些值,以便所有其

  • 我有一个使用yeoman、grunt和bower创建的AngularJS应用程序。 我有一个登录页面,它有一个检查身份验证的控制器。如果凭据是正确的,我重新路由到主页。 应用程序。js 登录ontroler.js 在我的主页上 在loginController中,我检查登录信息,如果成功,我在服务工厂中设置用户对象。我不知道这是否正确。 我需要的是,当用户登录时,它在user对象中设置一些值,以便

  • 使用,https://github.com/firebase/FirebaseUI-Android/tree/master/codelabs/chat作为登录的参考,我在键入时似乎遇到了问题 我只能键入Auth的提供者,而不能键入,为什么会这样,它提示我键入社会提供者。

  • 我一直在搜索net,试图找到任何定义如何在流星和响应路由器4中处理身份验证的地方。 基本上,我希望某些路由只对经过身份验证的用户可用。有相关文件吗? 阿西尔

  • 当使用Firebase身份验证匿名帐户时,它偶尔会在系统中创建一个新的用户ID,有时它会使用相同的用户ID。我真的希望每次都能创建相同的用户ID,这样匿名用户仍然可以在应用程序中维护相同的进度/数据。这实际上是我开始使用Firebase的原因。即使在重新启动应用程序等之后,我如何始终维护一个匿名帐户来保持相同的用户ID? 我希望用户每次以访客身份玩游戏时都能获得相同的ID。我看到有些应用程序在卸载

  • 我是Symfony2的新手,我正在尝试创建一个基本的注册系统。因此,在Symfony2文档的帮助下,我创建了这个security.yml: 我使用了这个路由: 根据http://symfony.com/doc/current/book/security.html#using-a-traditional-login-form我不需要为login_check路由实现控制器。然而,Symfony将这个错