Estoy escribiendo una pequeña aplicación AngularJS que tiene una vista de inicio de sesión y una vista principal, configurada así:
$routeProvider
.when('/main' , {templateUrl: 'partials/main.html', controller: MainController})
.when('/login', {templateUrl: 'partials/login.html', controller: LoginController})
.otherwise({redirectTo: '/login'});
Mi LoginController comprueba la combinación usuario / pase y establece una propiedad en $ rootScope que refleja esto:
function LoginController($scope, $location, $rootScope) {
$scope.attemptLogin = function() {
if ( $scope.username == $scope.password ) { // test
$rootScope.loggedUser = $scope.username;
$location.path( "/main" );
} else {
$scope.loginError = "Invalid user/pass.";
}
}
Todo funciona, pero si http://localhost/#/main
accedo termino saltando la pantalla de inicio de sesión. Quería escribir algo como "cada vez que cambie la ruta, si $ rootScope.loggedUser es nulo, redirigir a / login"
...
... Espere. ¿Puedo escuchar los cambios de ruta de alguna manera? Publicaré esta pregunta de todos modos y seguiré buscando.
Respuestas:
Después de sumergirme un poco en la documentación y el código fuente, creo que lo hice funcionar. ¿Quizás esto sea útil para alguien más?
Agregué lo siguiente a la configuración de mi módulo:
Lo único que parece extraño es que tuve que probar el nombre parcial (
login.html
) porque el "siguiente" objeto de ruta no tenía una URL o algo más. Tal vez hay una mejor manera?fuente
Esta es quizás una solución más elegante y flexible con la propiedad de configuración 'resolver' y las 'promesas' que permiten la carga de datos eventuales en el enrutamiento y las reglas de enrutamiento dependiendo de los datos.
Usted especifica una función en 'resolver' en la configuración de enrutamiento y en la función cargar y verificar datos, hacer todos los redireccionamientos. Si necesita cargar datos, devuelve una promesa, si necesita redirigir, rechace la promesa antes de eso. Todos los detalles se pueden encontrar en las páginas de documentación $ routerProvider y $ q .
Para las personas de habla rusa hay una publicación en habr " Вариант условного раутинга в AngularJS ".
fuente
ui.router
se usa, use en$stateProvider
lugar de$routeProvider
.He estado tratando de hacer lo mismo. Se le ocurrió otra solución más simple después de trabajar con un colega. Tengo un reloj configurado
$location.path()
. Eso hace el truco. Estoy empezando a aprender AngularJS y encuentro que esto es más limpio y legible.fuente
Una forma diferente de implementar la redirección de inicio de sesión es usar eventos e interceptores como se describe aquí . El artículo describe algunas ventajas adicionales, como detectar cuándo se requiere un inicio de sesión, poner en cola las solicitudes y volver a reproducirlas una vez que el inicio de sesión es exitoso.
Puede probar una demostración funcional aquí y ver la fuente de demostración aquí .
fuente
1. Establecer usuario global actual.
En su servicio de autenticación, configure el usuario autenticado actualmente en el ámbito raíz.
2. Configure la función de autenticación en cada ruta protegida.
3. Verifique la autenticación en cada cambio de ruta.
Alternativamente, puede establecer permisos en el objeto de usuario y asignar un permiso a cada ruta, luego verificar el permiso en la devolución de llamada del evento.
fuente
if (!user && !next.$$route.public)
next.$$route
? No encuentro nada en los documentos angulares que describan los argumentos que dan a un$routeChangeStart
evento, pero supongonext
y ¿curr
hay algún tipo de objeto de ubicación? El$$route
bit es difícil de google.$$route
propiedad es una variable privada de Angular. No debe confiar en eso, consulte por ejemplo: stackoverflow.com/a/19338518/1132101 : si lo hace, su código podría romperse cuando Angular cambie.$route.routes
para construir una lista (como en la respuesta de @ thataustin): obtener la ruta de la ubicación connext.originalPath
y el uso que para indexar$route.routes
:var auth = $route.routes[next.originalPath]
.Así es como lo hice, en caso de que ayude a alguien:
En la configuración, configuro un
publicAccess
atributo en las pocas rutas que quiero abrir al público (como iniciar sesión o registrarse):luego, en un bloque de ejecución, configuro un escucha en el
$routeChangeStart
evento que redirige a'/login'
menos que el usuario tenga acceso o la ruta sea de acceso público:Obviamente, podría cambiar la condición de
isLoggedIn
cualquier otra cosa ... simplemente mostrando otra forma de hacerlo.fuente
nextLoc.$$route.publicAccess
cierto.$route.routes[nextLoc.originalPath]
, que no usa una variable privada.nextLoc && nextLoc.publicAccess
!Lo estoy haciendo usando interceptores. He creado un archivo de biblioteca que se puede agregar al archivo index.html. De esta manera, tendrá un manejo de errores global para sus llamadas de servicio de descanso y no tendrá que preocuparse por todos los errores individualmente. Más abajo también pegué mi biblioteca de inicio de sesión de autenticación básica. Allí puede ver que también verifico el error 401 y redirijo a una ubicación diferente. Ver lib / ea-basic-auth-login.js
lib / http-error-handling.js
css / http-error-handling.css
index.html
lib / ea-basic-auth-login.js
Se puede hacer casi lo mismo para el inicio de sesión. Aquí tiene la respuesta a la redirección ($ location.path ("/ login")).
fuente
En su archivo app.js:
fuente
Es posible redirigir a otra vista con angular-ui-router . Para este propósito, tenemos el método
$state.go("target_view")
. Por ejemplo:fuente
Si no desea utilizar angular-ui-router, pero desea que sus controladores se carguen de manera diferida a través de RequireJS, hay un par de problemas con el evento
$routeChangeStart
al usar sus controladores como módulos RequireJS (carga diferida).No puede estar seguro de que el controlador se cargará antes de que
$routeChangeStart
se active; de hecho, no se cargará. Eso significa que no puede acceder a propiedades denext
ruta comolocals
o$$route
porque aún no están configuradas.Ejemplo:
Esto significa que no puede verificar los derechos de acceso allí.
Solución:
Como la carga del controlador se realiza por resolución, puede hacer lo mismo con su control de control de acceso:
Tenga en cuenta aquí que en lugar de usar el evento
$routeChangeStart
, estoy usando$routeChangeError
fuente
fuente