Angular
Tutorial Angular: Route Guards basados en interfaces
Aprende a usar Angular Route Guards para implementar autenticación y autorización en tu aplicación. Protege rutas, maneja navegación y pre-carga datos de manera eficiente.
Aprende Angular GRATIS y certifícate¿Qué es un route guard?
Un route guard en Angular es una interfaz que permite controlar la navegación a una ruta específica y decidir si dicha navegación debe ser permitida o no.
Los route guards se utilizan comúnmente para implementar lógicas de autenticación y autorización, aunque también pueden servir para diversas comprobaciones o condiciones antes de que se cargue una ruta.
Ejemplos de route guards basados en interfaces
- CanActivate: Este guard se ejecuta antes de que se active una ruta. Se usa principalmente para proteger rutas que requieren autenticación.
- CanDeactivate: Se utiliza para manejar la navegación fuera de una ruta. Es útil, por ejemplo, para advertir a los usuarios sobre la posible pérdida de cambios no guardados.
- CanActivateChild: Similar al
CanActivate
, pero se aplica a rutas hijas. Permite proteger rutas secundarias dentro de una aplicación. - CanLoad: Se usa para evitar que se cargue un módulo que se está cargando de manera diferida hasta que se cumpla alguna condición. Ideal para optimizar la carga de recursos en aplicaciones grandes.
- Resolve: Permite pre-cargar datos antes de que se active una ruta. Este guard es útil para asegurar que los datos necesarios estén disponibles antes de que la vista sea renderizada.
Crear un AuthGuard (CanActivate)
Para crear un guard utilizando la interfaz CanActivate
, seguimos estos pasos:
Generar un nuevo guard
Utilizamos Angular CLI para generar un guard. Esto se hace de la siguiente manera:
1.- Abre una terminal en el directorio raíz de tu proyecto Angular.
2.- Ejecuta el siguiente comando:
ng generate guard auth
O la versión abreviada:
ng g guard auth
3.- Angular CLI te preguntará qué interfaces quieres implementar. Selecciona CanActivate
usando las teclas de flecha y presiona la barra espaciadora para marcarla. Luego presiona Enter.
4.- El CLI generará el archivo auth.guard.ts
en la carpeta src/app
.
Implementar el método canActivate
En el archivo generado (auth.guard.ts
), implementamos la lógica de verificación de autenticación.
Ejemplo básico de uso
Para implementar un AuthGuard
en Angular, primero debemos crear un guard utilizando una de las interfaces de guard disponibles. En este ejemplo, usaremos CanActivate
, pero Angular ofrece otras interfaces como CanDeactivate
, CanActivateChild
, y CanLoad
para diferentes escenarios.
A continuación, se detalla el proceso paso a paso para crear un AuthGuard
básico, implementar un servicio de autenticación y proteger las rutas en la aplicación. Este enfoque se puede adaptar para usar otras interfaces de guard según las necesidades específicas del proyecto.
Aplicaciones con módulo raíz tradicional
Implementación del AuthGuard
Primero, creamos el AuthGuard
. Debemos asegurarnos de que este guard verifica si el usuario está autenticado antes de permitir el acceso a una ruta específica.
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service'; // Servicio de autenticación
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const isAuthenticated = this.authService.isLoggedIn(); // Método para verificar si está autenticado
if (!isAuthenticated) {
this.router.navigate(['login']); // Redirige al login si no está autenticado
return false;
}
return true;
}
}
Implementación del servicio de autenticación
El siguiente paso es implementar el servicio de autenticación (AuthService
). Este servicio debe tener un método que verifique si el usuario está autenticado o no.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private authenticated: boolean = false;
// Simulación de login
login(username: string, password: string): boolean {
if (username === 'user' && password === 'password') {
this.authenticated = true;
return true;
}
return false;
}
// Método que comprueba el estado de autenticación
isLoggedIn(): boolean {
return this.authenticated;
}
// Simulación de logout
logout() {
this.authenticated = false;
}
}
Integración del AuthGuard en las rutas de la aplicación
Una vez que tenemos implementado tanto el AuthGuard
como el AuthService
, podemos proceder a la integración del guard en las rutas de la aplicación para protegerlas.
Modificamos el módulo de rutas (AppRoutingModule
) para incluir el guard en las rutas que queremos proteger.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { HomeComponent } from './home/home.component'; // Componente protegido
import { LoginComponent } from './login/login.component'; // Componente de login
const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
{ path: 'login', component: LoginComponent },
{ path: '**', redirectTo: 'home' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Aplicaciones con Standalone Components
Implementación del AuthGuard
En aplicaciones standalone, el AuthGuard
se implementa como una función en lugar de una clase. Esto permite una sintaxis más concisa y el uso de la función inject()
para la inyección de dependencias.
// auth.guard.ts
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
export const authGuard = () => {
const authService = inject(AuthService);
const router = inject(Router);
if (authService.isLoggedIn()) {
return true;
}
return router.parseUrl('/login');
};
Implementación del servicio de autenticación
El servicio de autenticación permanece igual que en el ejemplo anterior, ya que los servicios funcionan de manera similar tanto en aplicaciones tradicionales como en standalone.
Configuración de rutas con el AuthGuard
En aplicaciones standalone, las rutas se configuran directamente en el archivo principal (generalmente main.ts
). Aquí, utilizamos bootstrapApplication
y provideRouter
para configurar la aplicación y sus rutas.
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { Routes, provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { authGuard } from './app/auth.guard';
const routes: Routes = [
{
path: 'home',
loadComponent: () => import('./app/home/home.component').then(m => m.HomeComponent),
canActivate: [authGuard]
},
{
path: 'login',
loadComponent: () => import('./app/login/login.component').then(m => m.LoginComponent)
},
{ path: '', redirectTo: '/home', pathMatch: 'full' },
];
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)]
}).catch(err => console.error(err));
Ejemplos prácticos
Crear un AuthGuard (CanActivate)
Para crear un guard utilizando la interfaz CanActivate
, seguimos estos pasos:
- Generar un nuevo guard: Utilizamos Angular CLI para generar un guard.
- Implementar el método
canActivate
: En el archivo generado (auth.guard.ts
), implementamos la lógica de verificación de autenticación.
Confirmación de salida con CanDeactivate
Este guard se utiliza para prevenir que un usuario abandone una página accidentalmente sin guardar cambios. Es particularmente útil en formularios o editores.
El CanDeactivateGuard
implementa la interfaz CanDeactivate
. Comprueba si el componente tiene un método canDeactivate()
y lo ejecuta. Este método puede devolver un booleano, una promesa o un observable.
// can-deactivate.guard.ts
import { CanDeactivateFn } from '@angular/router';
export type CanDeactivateComponent = {
canDeactivate: () => boolean | Promise<boolean> | import('rxjs').Observable<boolean>
};
export const canDeactivateGuard: CanDeactivateFn<CanDeactivateComponent> =
(component) => {
return component.canDeactivate ? component.canDeactivate() : true;
};
En el componente, implementamos la lógica real de confirmación. En este caso, se muestra un simple cuadro de diálogo de confirmación, pero en una aplicación real, podría comprobar si hay cambios no guardados y mostrar un mensaje más específico.
// edit.component.ts
import { Component } from '@angular/core';
import { CanDeactivateComponent } from './can-deactivate.guard';
@Component({
selector: 'app-edit',
standalone: true,
template: '<h1>Edit Component</h1>',
})
export class EditComponent implements CanDeactivateComponent {
canDeactivate(): boolean {
return confirm('Do you want to discard changes?');
}
}
Para usar este guard en las rutas:
// app.routes.ts
import { Routes } from '@angular/router';
import { EditComponent } from './edit.component';
import { canDeactivateGuard } from './can-deactivate.guard';
export const routes: Routes = [
{
path: 'edit',
component: EditComponent,
canDeactivate: [canDeactivateGuard]
},
// ... otras rutas
];
Cargar datos con Resolve
El resolver es una herramienta poderosa para precargar datos antes de que se active una ruta. Esto asegura que la información necesaria esté disponible antes de que se muestre el componente, mejorando la experiencia del usuario.
En este ejemplo, el DataResolver
implementa la interfaz Resolve
. Utiliza un DataService
para obtener los datos. El método resolve()
se ejecuta antes de que la ruta se active, y la navegación no se completa hasta que los datos se resuelven.
// data.resolver.ts
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { Observable } from 'rxjs';
import { DataService } from './data.service';
export const dataResolver: ResolveFn<any> = (
route,
state
): Observable<any> => {
const dataService = inject(DataService);
return dataService.getData();
};
Suponiendo que tenemos un DataService
:
// data.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
getData(): Observable<any> {
return of({ message: 'Datos precargados' });
}
}
En la configuración de rutas, asociamos el resolver a una ruta específica. Los datos resueltos estarán disponibles en el componente a través de ActivatedRoute
.
// app.routes.ts
import { Routes } from '@angular/router';
import { HomeComponent } from './home.component';
import { dataResolver } from './data.resolver';
export const routes: Routes = [
{
path: 'home',
component: HomeComponent,
resolve: { data: dataResolver }
},
// ... otras rutas
];
Proteger rutas hijas con CanActivateChild
CanActivateChild
es útil cuando tenemos un conjunto de rutas hijas que queremos proteger con la misma lógica de autorización. En lugar de aplicar un guard a cada ruta hija individualmente, podemos usar CanActivateChild
en la ruta padre.
El ChildAuthGuard
implementa CanActivateChild
. Su lógica es similar a un CanActivate
normal, pero se aplica a todas las rutas hijas. En este caso, verifica si el usuario está autenticado antes de permitir el acceso a cualquier ruta hija.
// child-auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateChildFn, Router } from '@angular/router';
import { AuthService } from './auth.service';
export const childAuthGuard: CanActivateChildFn = (childRoute, state) => {
const authService = inject(AuthService);
const router = inject(Router);
const isAuthenticated = authService.isLoggedIn();
if (!isAuthenticated) {
router.navigate(['login']);
return false;
}
return true;
};
Suponiendo que tenemos un AuthService
:
// auth.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthService {
isLoggedIn(): boolean {
// Implementación real de verificación de autenticación
return true; // Ejemplo simplificado
}
}
En la configuración de rutas, aplicamos el guard a la ruta padre (dashboard
), y todas sus rutas hijas heredarán esta protección.
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivateChild: [ChildAuthGuard],
children: [
{ path: 'profile', component: ProfileComponent },
{ path: 'settings', component: SettingsComponent },
],
},
];
Controlar la carga diferida con CanLoad
CanLoad
es un guard especialmente diseñado para trabajar con la carga diferida (lazy loading) de módulos. Previene que un módulo se cargue si no se cumplen ciertas condiciones, lo que puede ser útil para optimizar el rendimiento y la seguridad.
El LoadGuard
implementa CanLoad
. Verifica si el usuario está autenticado antes de permitir la carga del módulo. Si el usuario no está autenticado, redirige al login y previene la carga del módulo.
// load.guard.ts
import { inject } from '@angular/core';
import { CanLoadFn, Router } from '@angular/router';
import { AuthService } from './auth.service';
export const loadGuard: CanLoadFn = (route, segments) => {
const authService = inject(AuthService);
const router = inject(Router);
const isAuthenticated = authService.isLoggedIn();
if (!isAuthenticated) {
router.navigate(['login']);
return false;
}
return true;
};
En la configuración de rutas, aplicamos CanLoad
a una ruta que usa loadChildren
para cargar un módulo de forma diferida. Esto asegura que el módulo solo se cargará si el guard lo permite.
// app.routes.ts
import { Routes } from '@angular/router';
import { loadGuard } from './load.guard';
export const routes: Routes = [
{
path: 'admin',
loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES),
canLoad: [loadGuard],
},
// ... otras rutas
];
Para el módulo admin, ahora usaremos un archivo de rutas standalone:
// admin/admin.routes.ts
import { Routes } from '@angular/router';
import { AdminComponent } from './admin.component';
export const ADMIN_ROUTES: Routes = [
{ path: '', component: AdminComponent },
// ... otras rutas admin
];
El componente Admin puede ser standalone:
// admin/admin.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-admin',
standalone: true,
template: '<h1>Admin Dashboard</h1>'
})
export class AdminComponent {}
Ejercicios de esta lección Route Guards basados en interfaces
Evalúa tus conocimientos de esta lección Route Guards basados en interfaces con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Signals en Angular
Guards funcionales
Decodificar JWT en Angular
Servicio con HttpClient
Ciclo de vida de componentes en Angular
Gestión de productos de Fake Store API
Data binding en Angular
Routes sin módulos en Angular
Router en Angular
Instalación de Angular
Route Guards basados en interfaces
La directiva @if en Angular
Formularios reactivos en Angular
Servicios en Angular
Interceptor funcional
Servicio con Array
La directiva @for en Angular
Interceptores HTTP
Componentes standalone true
Formularios con ngModel en Angular
Routes en Angular
Comunicación entre componentes Angular
Parámetros en rutas con ActivatedRoute
CRUD de Restaurantes y Platos
Tablas en Angular Material
Formulario de registro de usuarios
Instalación y uso de NgBoostrap
Desarrollo de componentes Angular
JWT en Angular
Formularios reactivos en Angular
Formularios en Angular Material
Layout con Angular Material
Effects en Angular
Data binding
HttpClient en servicios de Angular
Desarrollo de módulos Angular
Comandos Angular CLI
Subir archivo en formularios
La directiva routerLink en Angular
Todas las lecciones de Angular
Accede a todas las lecciones de Angular y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación Angular
Introducción Y Entorno
Comandos Angular Cli
Introducción Y Entorno
Desarrollo De Componentes Angular
Componentes
Data Binding En Angular
Componentes
Ciclo De Vida De Componentes En Angular
Componentes
Comunicación Entre Componentes Angular
Componentes
La Directiva @If En Angular
Componentes
La Directiva @For En Angular
Componentes
Componentes Standalone
Componentes
Desarrollo De Módulos Angular
Módulos
Routes En Angular
Enrutado Y Navegación
Router En Angular
Enrutado Y Navegación
La Directiva Routerlink En Angular
Enrutado Y Navegación
Parámetros En Rutas Con Activatedroute
Enrutado Y Navegación
Routes Sin Módulos En Angular
Enrutado Y Navegación
Servicios En Angular
Servicios E Inyección De Dependencias
Httpclient En Servicios De Angular
Servicios E Inyección De Dependencias
Formularios Con Ngmodel En Angular
Formularios
Formularios Reactivos En Angular
Formularios
Subir Archivo En Formularios
Formularios
Layout Con Angular Material
Integración Con Angular Material
Tablas En Angular Material
Integración Con Angular Material
Formularios En Angular Material
Integración Con Angular Material
Instalación Y Uso De Ngboostrap
Integración Con Bootstrap Css
Signals En Angular
Signals Y Reactividad
Effects En Angular
Signals Y Reactividad
Route Guards Basados En Interfaces
Autenticación Y Autorización
Guards Funcionales
Autenticación Y Autorización
Interceptores Http Basados En Interfaz
Autenticación Y Autorización
Interceptores Http Funcionales
Autenticación Y Autorización
Seguridad Jwt En Angular
Autenticación Y Autorización
Decodificar Tokens Jwt En Angular
Autenticación Y Autorización
Certificados de superación de Angular
Supera todos los ejercicios de programación del curso de Angular y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
Entender los diferentes tipos de Route Guards en Angular.
Implementar CanActivate para proteger rutas que requieren autenticación.
Usar CanDeactivate para manejar navegación fuera de una ruta.
Proteger rutas hijas con CanActivateChild.
Controlar la carga diferida de módulos con CanLoad.
Pre-cargar datos antes de la activación de una ruta con Resolve.
Integrar y configurar Route Guards en aplicaciones tanto tradicionales como standalone.