Introducción
En aplicaciones Angular, las guardias de ruta (route guards) son una herramienta esencial para controlar el acceso a diferentes rutas basándose en ciertas condiciones. Las guardias de ruta permiten proteger rutas específicas, asegurando que solo los usuarios autorizados o que cumplen ciertos criterios puedan acceder a ellas.
Tipos de Guardias de Ruta
Angular proporciona varios tipos de guardias de ruta que se pueden implementar:
- CanActivate: Determina si una ruta puede ser activada.
- CanActivateChild: Determina si las rutas hijas de una ruta pueden ser activadas.
- CanDeactivate: Determina si se puede salir de una ruta.
- CanLoad: Determina si un módulo puede ser cargado.
- Resolve: Prepara datos antes de que se active una ruta.
Implementación de Guardias de Ruta
Paso 1: Crear una Guardia de Ruta
Para crear una guardia de ruta, utilizamos el Angular CLI. Por ejemplo, para crear una guardia AuthGuard
que implemente CanActivate
, ejecutamos el siguiente comando:
Este comando generará un archivo auth.guard.ts
con una estructura básica.
Paso 2: Implementar la Lógica de la Guardia
Editamos el archivo auth.guard.ts
para implementar la lógica de la guardia. A continuación, se muestra un ejemplo de una guardia que verifica si el usuario está autenticado:
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (this.authService.isLoggedIn()) { return true; } else { this.router.navigate(['/login']); return false; } } }
Paso 3: Registrar la Guardia en las Rutas
Para utilizar la guardia AuthGuard
, la registramos en las rutas correspondientes en el archivo de configuración de rutas (app-routing.module.ts
):
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { LoginComponent } from './login/login.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, { path: '', redirectTo: '/home', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Ejemplo Completo
A continuación, se muestra un ejemplo completo que incluye un servicio de autenticación (auth.service.ts
), la guardia de ruta (auth.guard.ts
) y la configuración de rutas (app-routing.module.ts
).
auth.service.ts
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { private loggedIn = false; login() { this.loggedIn = true; } logout() { this.loggedIn = false; } isLoggedIn(): boolean { return this.loggedIn; } }
auth.guard.ts
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (this.authService.isLoggedIn()) { return true; } else { this.router.navigate(['/login']); return false; } } }
app-routing.module.ts
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { LoginComponent } from './login/login.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, { path: '', redirectTo: '/home', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Ejercicio Práctico
Ejercicio
- Objetivo: Crear una guardia de ruta que permita el acceso a una ruta solo si el usuario tiene un rol específico.
- Pasos:
- Crear un servicio
RoleService
que gestione los roles de los usuarios. - Crear una guardia
RoleGuard
que implementeCanActivate
y verifique el rol del usuario. - Registrar la guardia en una ruta específica.
- Crear un servicio
Solución
role.service.ts
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class RoleService { private userRole: string = 'guest'; setRole(role: string) { this.userRole = role; } getRole(): string { return this.userRole; } }
role.guard.ts
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; import { RoleService } from './role.service'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class RoleGuard implements CanActivate { constructor(private roleService: RoleService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { const expectedRole = next.data.expectedRole; if (this.roleService.getRole() === expectedRole) { return true; } else { this.router.navigate(['/unauthorized']); return false; } } }
app-routing.module.ts
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { LoginComponent } from './login/login.component'; import { UnauthorizedComponent } from './unauthorized/unauthorized.component'; import { RoleGuard } from './role.guard'; const routes: Routes = [ { path: 'home', component: HomeComponent, canActivate: [RoleGuard], data: { expectedRole: 'admin' } }, { path: 'login', component: LoginComponent }, { path: 'unauthorized', component: UnauthorizedComponent }, { path: '', redirectTo: '/home', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Conclusión
Las guardias de ruta en Angular son una herramienta poderosa para controlar el acceso a diferentes partes de una aplicación. Permiten implementar lógica de seguridad y autorización de manera eficiente, asegurando que solo los usuarios adecuados puedan acceder a ciertas rutas. En este módulo, hemos aprendido a crear y utilizar diferentes tipos de guardias de ruta, así como a implementar una guardia personalizada basada en roles de usuario.
Curso de Angular
Módulo 1: Introducción a Angular
- ¿Qué es Angular?
- Configuración del Entorno de Desarrollo
- Arquitectura de Angular
- Primera Aplicación Angular
Módulo 2: Componentes de Angular
- Entendiendo los Componentes
- Creación de Componentes
- Plantillas de Componentes
- Estilos de Componentes
- Interacción entre Componentes
Módulo 3: Enlace de Datos y Directivas
- Interpolación y Enlace de Propiedades
- Enlace de Eventos
- Enlace de Datos Bidireccional
- Directivas Incorporadas
- Directivas Personalizadas
Módulo 4: Servicios e Inyección de Dependencias
- Introducción a los Servicios
- Creación y Uso de Servicios
- Inyección de Dependencias
- Inyectores Jerárquicos
Módulo 5: Enrutamiento y Navegación
Módulo 6: Formularios en Angular
- Formularios Basados en Plantillas
- Formularios Reactivos
- Validación de Formularios
- Formularios Dinámicos
Módulo 7: Cliente HTTP y Observables
- Introducción al Cliente HTTP
- Realizando Solicitudes HTTP
- Manejo de Respuestas HTTP
- Uso de Observables
- Manejo de Errores
Módulo 8: Gestión de Estado
- Introducción a la Gestión de Estado
- Uso de Servicios para la Gestión de Estado
- NgRx Store
- NgRx Effects
- NgRx Entity
Módulo 9: Pruebas en Angular
- Pruebas Unitarias
- Pruebas de Componentes
- Pruebas de Servicios
- Pruebas de Extremo a Extremo
- Simulación de Dependencias
Módulo 10: Conceptos Avanzados de Angular
- Angular Universal
- Optimización del Rendimiento
- Internacionalización (i18n)
- Pipes Personalizados
- Animaciones en Angular