Confundiendo $ locationChangeSuccess y $ stateChangeStart

Estoy tratando de hacer algo de autenticación con AngularUI Router. $urlRouter.sync() parece exactamente lo que necesito. Sin embargo, eso solo está disponible cuando intercepto $locationChangeSuccess . Pero cuando lo hago, $state.current.name está vacío, mientras que yo quiero que sea el estado actual.

Aquí está mi código hasta ahora:

 $rootScope.$on('$locationChangeSuccess', function(event, next, nextParams) { event.preventDefault(); if ($state.current.name === 'login') { return userService.isAuthenticated().then(function(response) { var authenticated; authenticated = response.authenticated; return alert(authenticated); }); } }); 

¿Alguna sugerencia sobre lo que estoy haciendo mal?

Sugeriría ir más ” UI-Router way”. Deberíamos usar $rootScope.$on('$stateChangeStart' evento $rootScope.$on('$stateChangeStart' donde $state.current se proporcionaría correctamente. Aquí hay un ejemplo de trabajo

Observemos una solución simple (pero no ingenua) , que podría extenderse en cualquier grado más adelante. Además, si le gusta este enfoque, aquí hay una implementación mucho más completa: autenticación de inicio de sesión ui-router angular

En primer lugar, vamos a tener nuestro servicio de usuario definido así:

 .factory('userService', function ($timeout, $q) { var user = undefined; return { // async way how to load user from Server API getAuthObject: function () { var deferred = $q.defer(); // later we can use this quick way - // - once user is already loaded if (user) { return $q.when(user); } // server fake call, in action would be $http $timeout(function () { // server returned UN authenticated user user = {isAuthenticated: false }; // here resolved after 500ms deferred.resolve(user) }, 500) return deferred.promise; }, // sync, quick way how to check IS authenticated... isAuthenticated: function () { return user !== undefined && user.isAuthenticated; } }; }) 

Entonces, usamos async (aquí $timeout ) para cargar un objeto de user desde un servidor. En nuestro ejemplo, tendrá una propiedad {isAuthenticated: false } , que se usará para verificar si está autenticada.

También hay un método de sincronización isAuthenticated() que, hasta que el usuario esté cargado y permitido, siempre devuelve false .

Y ese sería nuestro oyente del evento '$stateChangeStart' :

 .run(['$rootScope', '$state', 'userService', function ($rootScope, $state, userService) { $rootScope.$on('$stateChangeStart', function (event, toState, toParams , fromState, fromParams) { // if already authenticated... var isAuthenticated = userService.isAuthenticated(); // any public action is allowed var isPublicAction = angular.isObject(toState.data) && toState.data.isPublic === true; if (isPublicAction || isAuthenticated) { return; } // stop state change event.preventDefault(); // async load user userService .getAuthObject() .then(function (user) { var isAuthenticated = user.isAuthenticated === true; if (isAuthenticated) { // let's continue, use is allowed $state.go(toState, toParams) return; } // log on / sign in... $state.go("login"); }) ... 

Lo que estamos comprobando primero es si el usuario ya está cargado y autenticado ( var isAuthenticated = ... ) . A continuación daremos verde a cualquier método público. Esto se hace con la propiedad de data {} de la definición de objeto de estado (ver Adjuntar Datos Personalizados a Objetos de Estado )

Y eso es. En el caso de estados definidos como en un fragmento a continuación, podemos experimentar:

  • el 'public' , el 'home' están permitidos a cualquiera
  • el 'private' , 'private' se redirigirá al inicio de sesión si está isAuthenticated === false
  • el 'login' en este ejemplo proporciona una manera rápida de activar / desactivar Autentificación

     // States $stateProvider // public .state('home', { url: "/home", templateUrl: 'tpl.html', data: { isPublic: true }, }) .state('public', { url: "/public", templateUrl: 'tpl.html', data: { isPublic: true }, }) // private .state('private', { url: "/private", templateUrl: 'tpl.html', }) .state('private2', { url: "/private2", templateUrl: 'tpl.html', }) // login .state('login', { url: "/login", templateUrl: 'tpl.html', data: { isPublic: true }, controller: 'loginCtrl', }) 

Comprueba que todo aquí

Algunos otros recursos:

  • Autenticación de inicio de sesión de ui-router angular
  • Enrutador de UI angular: estados nesteds para el hogar para diferenciar las conexiones iniciadas y las salidas
  • otros data estado y autenticación