Proteger tus vistas con Angular y sus guards
Proteger tus vistas con Angular y sus guards
Imagínense que tienen un sistema web en donde cualquier usuario puede registrarse y loguearse y como la mayoría de los sistemas, poseen una zona de panel de administración, a la cual, solo los usuarios Administradores pueden entrar. ¿Cómo solucionarías esto? Fácil, dependiendo de qué usuario este logueado, me fijo que rol o permiso tiene y lo habilito a ingresar al panel o no, esto sin importar el framework o lenguaje se debe cumplir. Ahora bien, imagínense el caso de que tengan que bloquear el acceso a 20 vistas, ¿No se vuelve muy tedioso tener que hacer el código en cada una de ellas para chequear si tiene permisos o no? Bueno, en el caso de Angular, aquí se podrían usar los guards (además de muchas otras funciones que poseen).
¿Qué es un guard?
Los guards son métodos que nos permiten acceder a cierta rutas, dependiendo de la condición que nosotros queramos, también se podrían utilizar para evitar cargar modulos, etc. Allí podemos hacer validaciones, llamar al backend o cualquier cosa que necesitemos. Dentro de todo lo que son los guards, existen 5 tipos:
CanActivate: Según una condición, que nosotros queramos, ingresamos a la ruta o página.
CanActivateChild: Funciona de la misma manera que CanActivate, la única diferencia es que se utiliza para rutas hijas (lazy loading).
CanDeactivate: Es lo opuesto a CanActivate, según una condición, nos permite salir de una ruta o una página. Se puede utilizar por ejemplo, cuando tenemos un formulario y queremos preguntar si desea descartar los cambios del mismo.
CanLoad: Lo podemos utilizar para evitar al usuario cargar módulos innecesarios.
Resolve: Podríamos utilizarlo para retrasar la representación de un componente deseado hasta que se hayan obtenido los resultados necesarios.
Nosotros vamos a ver el más común, CanActivate, el resto se aplican de forma similar.
¿Cómo se crea un guard?
El guard se genera como si fuese un servicio, debemos hacerlo inyectable. Estos pueden retornar true o false, una promesa o un observable.
Lo que vamos a hacer es crear un guard que nos permita bloquearle la ruta a un usuario o no, dependiendo de su rol y allí pondremos el método canActivate
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRoute, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import {AuthService} from '../../Auth.service.ts'
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) { }
public canActivate()
{
if (this.authService.getRol() !== 'Admin') //Obtenemos en nuestro servicio el rol y nos fijamos si es igual o no al de 'Admin
{
console.log('Usted no posee permisos para acceder a esta ruta');
this.router.navigate(['/']); //Lo enviamos a la página que queramos
return false;
}
return true; //Este camino deja continuar con la vista con normalidad
}
}
Lo que hace este código es, chequear si tenemos el rol de admin, en caso de no tenerlo nos redirige a la vista de error y retorna false y en caso contrario muestra la vista con normalidad.
Ahora debemos decirle en que vista iría este guard, para eso vamos al routing y alli lo incluimos en la ruta deseada.
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PanelComponent} from './panel.component';
import { AuthGuard} from 'src/app/guards/auth.guard';
const routes: Routes = [
{
path: '',
component: PanelComponent,
canActivate: [AuthGuard] //Acá indicamos cual es el guard y que tipo es
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Por último debemos incluirlo dentro de nuestros providers del modulo correspondiente, de la siguiente manera:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthGuard} from './guards/auth.guard';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [AuthGuard], //Agregamos a los providers el guard
bootstrap: [AppComponent]
})
export class AppModule { }
Con esto estaría finalizado nuestro guard.
Si deseamos realizar un guard más genérico para, según la ruta y los permisos, permitirle entrar o no, lo que podríamos hacer, es obtener la ruta a donde quiere ir el usuario y según eso chequear que permiso tiene. Lo único que cambiaría con respecto al que hicimos es qué el método canActivate recibirá un route del tipo ActivatedRouteSnapshot
y un state del tipo RouterStateSnapshot
quedándonos asi:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
Luego haremos lo que corresponda según el caso.
Conclusión
Hoy vimos como proteger tus vistas con Angular y sus guards y los distintos tipos que existen, dependiendo del caso verás si utilizar una o la otra, pero esto nos simplifica mucho el trabajo a la hora de realizar estas validaciones.