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
RoleServiceque gestione los roles de los usuarios. - Crear una guardia
RoleGuardque implementeCanActivatey 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
