javascript - ejemplos - ng-init
AngularJS | manejar el enrutamiento antes de que se carguen (5)
Angular-http-auth le permite manejar la autorización de manera muy elegante en el nivel HTTP (cuando se busca una plantilla) y solicitar un inicio de sesión si es necesario. Todo eso sin siquiera cargar la plantilla (ni el controlador) si se deniega la autorización. Claramente lo mejor que he visto hasta ahora.
Deseo crear una verificación de autenticación simple para mis rutas por servicio externo.
Defino los requisitos de acceso en el objeto de ruta:
$routeProvider
.when(''/'', {
templateUrl: ''src/app/views/index.html'',
controller: ''indexCtrl'',
authenticated: true
})
.when(''/login'', {
templateUrl: ''src/app/views/login.html'',
controller: ''loginCtrl'',
anonymous: true
})
.otherwise({
redirectTo: ''/''
})
;
Luego, verifico si tengo permiso dentro del evento $routeChangeStart
.
$rootScope.$on(''$routeChangeStart'', function (event, next) {
if(next.authenticated && !$myService.isLoggedin())
$location.path("/login");
else if(next.anonymous && $myService.isLoggedin())
$location.path("/secured");
});
En realidad funciona
Si el usuario no está autenticado, lo mueve a la página de inicio de sesión, si está autenticado pero la ruta es para usuarios anónimos, solo los mueve a otra página, etc.
PERO, ¡esta redirección realmente ocurre después de que los controladores y las plantillas se cargan! Y hace que mi controlador haga una solicitud innecesaria a mi API REST, incluso si no estoy autenticado.
¿Cómo puedo manejar la ruta antes de que se procesen?
Ejemplo de resolución de Angularjs:
.when(''/profile'', {
templateUrl: ''views/profile.html'',
controller: ''ProfileCtrl'',
resolve: {
app: function($q, $rootScope, $location) {
var defer = $q.defer();
if ($rootScope.currentUser == undefined) {
$location.path(''/login'');
};
defer.resolve();
return defer.promise;
}
}
Intenta usar la propiedad de resolve
de la ruta. Resuelve todas las funciones / dependencias pasadas a él antes de que se cargue cualquier controlador o plantilla. En caso de que la dependencia devuelva una promesa, hasta que se resuelva, no se carga nada.
Intente pasar su servicio de autenticación para resolver y redirigir en caso de fallo de autenticación.
Por favor, eche un vistazo -> https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw
$ stateProvider usa $ routeProvider debajo. Este wiki te dará más ideas. https://github.com/angular-ui/ui-router/wiki#resolve
Mi solución combinaba $locationChangeStart
y $routeChangeStart
:
$rootScope.$on(''$locationChangeStart'', function (event) {
//If login data not available, make sure we request for it
if($facebook.isConnected()==null) {
$facebook.getLoginStatus();
event.preventDefault();
return;
}
var next=parseRoute().$$route;
if(!Auth.loginCheck(next))
event.preventDefault();
});
Copié parseRoute()
de angular-route.js
para analizar la URL dada para enrutar ...
Luego construyo mi controlador de verificación de inicio de sesión ( Auth.loginCheck
) de manera que si falla, devuelva falso.
También uso $routeChangeStart
para manejar $route.reload()
, así que ahora, después de cada cambio en mi estado de autenticación, solo hago $route.reload()
:
$rootScope.$on(''$routeChangeStart'', function (event, next) {
Auth.loginCheck(next);
});
Finalmente, me aseguro de que este servicio personalizado siempre se ejecute utilizando el método simple run()
.
Editar:
Ahora estamos usando ngAuth, un módulo que diseñamos para resolver ese problema exacto (basado en la respuesta que di aquí antes).
Finalmente, desarrollamos un módulo angular que resolvió este problema. Este módulo se basa en la respuesta que publiqué aquí anteriormente.
Debido a las solicitudes aquí, publicamos una versión beta que ahora funciona: http://github.com/GoDisco/ngAuth
Sientase libre de usarlo.
Utilice $ routeProvider resolviendo
.when(''/'', {
templateUrl: ''src/app/views/index.html'',
controller: ''indexCtrl'',
resolve: function($q, $location) {
var deferred = $q.defer();
deferred.resolve();
if (!isAuthenticated) {
$location.path(''/login'');
}
return deferred.promise;
}
})