角度:处理重新加载页面和用户身份验证

Angular: Dealing with reload page and User Authentication

本文关键字:身份验证 用户 加载 处理 新加载 角度      更新时间:2023-09-26

我一直在一个记录用户的应用程序中工作。一旦用户被记录,用户的信息就会存储在服务中,cookie 就会与身份验证令牌一起存储。喜欢这个:

angular
 .module('MyModule')
 .service('AuthService', service);
service.$inject = ['$cookieStore', '$resource'];
function service($cookieStore, $resource){
  var self = this,
      user = null; 
  self.loginResource = $resource('my_path_to_login_resource');
  self.login = login;
  self.getUser = getUser;
  self.reloadUser = reloadUser; 

  function login(_userCredentials){
    var userResource = new self.loginResource(_userCredentials);
    return userResource.$save()
           .then(setUser);
  }
  function setUser(_userResponse){
    user = _userResponse.toJSON();
  }
  function getUser(){
    return user;
  }
  function reloadUser(_token){
    return self.loginResource()
            .get(_token)
            .then(setUser);
  }
}

当我需要处理应用程序的路由时,使用 ui-router 我这样做: 角 .module('MyModule') .run(runFn);

  runFn.$inject = ['$state', '$rootScope', 'AuthService', '$cookieStore'];
  function runFn($state, $rootScope, AuthService, $cookieStore) {
    $rootScope.$on('$stateChangeSuccess', stateTransitioned);
    function stateTransitioned(e, toState, toParams, fromState, fromParams) {
      var pageRealoaded = fromState.name? false : true;
      if(AuthService.getUser()){
        //DEALING WITH STATES TRANSITIONS
      }
      else{
         if($cookieStore.get('auth_token') && pageRealoaded){
            //ENSURE THAT THE USER IS LOGGED WHEN THE STATE IS CHANGED
            AuthService.reloadUser.then(function(){
              $state.go(toState.name);
            })
            .catch($state.go.bind(null,'login'));

           //I DON'T KNOW HOW AVOID THAT THE STATE IS LOADED UNTIL THE USER
           //HAVE BEEN LOGGED
         }
         else{
           $state.go('login');
         }
      }
    }
  }

当页面重新加载时,使用存储的令牌,我尝试等待该用户已登录,然后,如果成功,则重定向到状态toState.name,如果错误,则重定向到登录。我的问题:

1. 如何避免状态加载到用户登录?

2. 我处理此案的架构是否正确?关于更好的结构的建议?

我建议您使用 ui-router 的解析功能来确保用户在进入状态之前始终经过身份验证。

请参阅此处的 ui-router wiki:https://github.com/angular-ui/ui-router/wiki#resolve

像这样的东西应该阻止身份验证之前的状态输入。

.state('secure', {
    resolve: {
        user: function(AuthService, $state) {
            // State will only be entered if this resolves.
            return AuthService.resolveUser()
                .catch(function(error) {
                    $state.go('login');
                })
       }
    },
    template: '<div>Secret Page</div>
})

我还把这支笔和一个工作的例子放在一起:http://codepen.io/marcus-r/pen/eZKbYV?editors=1010

最后,对于我的第一个问题,我创建了以下示例,该示例演示了在成功记录用户之前如何防止状态更改。

http://codepen.io/gpincheiraa/pen/zqLYZz

在这个例子中,当我转到"state3"时,我等到用户登录,然后重定向到状态

angular
  .module('exampleApp', ['ui.router']);
angular
  .module('exampleApp')
  .config(configFn);
configFn.$inject = ['$stateProvider', '$urlRouterProvider'];
    function configFn($stateProvider, $urlRouterProvider){
      $urlRouterProvider.otherwise('state1');
        $stateProvider
         .state('state1', {
             url: '/state1',
           controller: ['$state', function($state){
               var  vm = this;
                 vm.current = $state.current.name;
                 vm.goTwo = function(){$state.go('state2');};
             }] ,
             controllerAs: 'one',
             template: '<h1>{{one.current}}</h1><button ng-click="one.goTwo()">Go to state 2</button>'
         })
        .state('state2', {
             url: '/state2',
           controller: ['$state', function($state){
               var  vm = this;
                 vm.current = $state.current.name;
                 vm.goThree = function(){$state.go('state3');};
             }] ,
             controllerAs: 'two',
             template: '<h1>{{two.current}}</h1><button ng-click="two.goThree()">Go to state 3</button>'
         })
        .state('state3', {
             url: '/state3',
           controller: ['$state', function($state){
               var  vm = this;
                 vm.current = $state.current.name;
             }] ,
             controllerAs: 'three',
             template: '<h1>{{three.current}}</h1>'
         })
    }
    angular
     .module('exampleApp')
     .run(runFn);
    runFn.$inject  = ['$rootScope','$timeout','$state'];
    function runFn($rootScope, $timeout, $state){
        var logged = false;
        $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
            console.log(toState.name);
            if(toState.name === 'state3' && !logged){
                //Fake like a user take a 1 second to login in server
                $timeout(function(){
                    logged = true;
                    console.log('login ok');
                    $state.go(toState.name);
                },1000)
                console.log('while the user not loggin, prevent the state change');
                event.preventDefault();
            }
        })

        }