Saltar al contenido

Guardias múltiples de Angular 4 – Secuencia de ejecución

Agradeceríamos tu ayuda para compartir nuestras crónicas en referencia a las ciencias de la computación.

Solución:

Elegí un camino diferente: anidar a mis guardias y convertirlos en dependencias entre sí.

tengo un RequireAuthenticationGuard y un RequirePermissionGuard. Para la mayoría de las rutas, ambos deben ejecutarse, pero hay un orden específico que necesito.

El RequireAuthenticationGuard depende de mis servicios de autenticación para comprobar si la sesión actual está autenticada.

El RequirePermissionGuard depende de mis servicios de autenticación para comprobar si la sesión actual está autorizada para una ruta.

Agrego el RequireAuthenticationGuard como una dependencia del constructor de RequirePermissionGuard y solo comience a verificar los permisos si se ha determinado la autenticación.

require-authentication.guard.ts

constructor(
    private userSessionSerivce: UserSessionService) 

canActivate(
    _route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
): Observable 
    return this.validateAuthentication(state.url);

require-permission.guard.ts

constructor(
    private permissionService: PermissionService,
    /**
    * We use the RequireAuthenticationGuard internally
    * since Angular does not provide ordered deterministic guard execution in route definitions
    *
    * We only check permissions once authentication state has been determined
    */
    private requireAuthenticationGuard: RequireAuthenticatedGuard,
) 

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
): Observable 

Usando un Maestro de la guardia para disparar, los protectores de aplicaciones pueden hacer el truco.

EDITAR: agregando el fragmento de código para una mejor comprensión.

Enfrenté un problema similar y así es como lo resolví:


Solución

La idea es crear un maestro de la guardia y dejar que el maestro de la guardia se encargue de la ejecución de otros guardias.

El configuración de enrutamiento en este caso, contendrá maestro de la guardia como el único guardia.

Para que el guardia maestro sepa sobre los guardias que se activarán para rutas específicas, agregue un data propiedad en Route.

El data la propiedad es una key par de valores que nos permite adjuntar datos con las rutas.

A continuación, se puede acceder a los datos en los guardias utilizando ActivatedRouteSnapshot parámetro de canActivate método en la guardia.

La solución parece complicada, pero garantizará el funcionamiento adecuado de las protecciones una vez que se integre en la aplicación.

El siguiente ejemplo explica este enfoque:


Ejemplo

1. Objeto de constantes para mapear todos los protectores de aplicaciones –

export const GUARDS = 
    GUARD1: "GUARD1",
    GUARD2: "GUARD2",
    GUARD3: "GUARD3",
    GUARD4: "GUARD4",

2. Protección de aplicaciones –

import  Injectable  from "@angular/core";
import  Guard4DependencyService  from "./guard4dependency";

@Injectable()
export class Guard4 implements CanActivate 
    //A  guard with dependency
    constructor(private _Guard4DependencyService:  Guard4DependencyService) 

    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise 
        return new Promise((resolve: Function, reject: Function) => 
            //logic of guard 4 here
            if (this._Guard4DependencyService.valid()) 
                resolve(true);
             else 
                reject(false);
            
        );
    

3. Configuración de enrutamiento –

import  Route  from "@angular/router";
import  View1Component  from "./view1";
import  View2Component  from "./view2";
import  MasterGuard, GUARDS  from "./master-guard";
export const routes: Route[] = [
    
        path: "view1",
        component: View1Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by 
        //masteer guard to execute guard1 and guard 2
        data: 
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2
            ]
        
    ,
    
        path: "view2",
        component: View2Component,
        //attach master guard here
        canActivate: [MasterGuard],
        //this is the data object which will be used by 
        //masteer guard to execute guard1, guard 2, guard 3 & guard 4
        data: 
            guards: [
                GUARDS.GUARD1,
                GUARDS.GUARD2,
                GUARDS.GUARD3,
                GUARDS.GUARD4
            ]
        
    
];

4. Maestro de la guardia –

import  Injectable  from "@angular/core";
import  CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router  from "@angular/router";

//import all the guards in the application
import  Guard1  from "./guard1";
import  Guard2  from "./guard2";
import  Guard3  from "./guard3";
import  Guard4  from "./guard4";

import  Guard4DependencyService  from "./guard4dependency";

@Injectable()
export class MasterGuard implements CanActivate 

    //you may need to include dependencies of individual guards if specified in guard constructor
    constructor(private _Guard4DependencyService:  Guard4DependencyService) 

    private route: ActivatedRouteSnapshot;
    private state: RouterStateSnapshot;

    //This method gets triggered when the route is hit
    public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise 

        this.route = route;
        this.state = state;

        if (!route.data) 
            Promise.resolve(true);
            return;
        

        //this.route.data.guards is an array of strings set in routing configuration

        if (!this.route.data.guards 

    //Execute the guards sent in the route data 
    private executeGuards(guardIndex: number = 0): Promise 
        return this.activateGuard(this.route.data.guards[guardIndex])
            .then(() => 
                if (guardIndex < this.route.data.guards.length - 1) 
                    return this.executeGuards(guardIndex + 1);
                 else 
                    return Promise.resolve(true);
                
            )
            .catch(() => 
                return Promise.reject(false);
            );
    

    //Create an instance of the guard and fire canActivate method returning a promise
    private activateGuard(guardKey: string): Promise  Guard3 

Desafíos

Uno de los desafíos de este enfoque es la refactorización del modelo de enrutamiento existente. Sin embargo, se puede hacer por partes, ya que los cambios no se romperán.

Espero que esto ayude.

Eche un vistazo a esta guía angular (enlace). “Si estuviera utilizando una API del mundo real, podría haber un retraso antes de que el servidor devuelva los datos que se mostrarán. No desea mostrar un componente en blanco mientras espera los datos.

Es preferible obtener previamente los datos del servidor para que estén listos en el momento en que se activa la ruta. Esto también le permite manejar errores antes de enrutar al componente …

En resumen, desea retrasar la renderización del componente enrutado hasta que se hayan obtenido todos los datos necesarios.

Necesitas un solucionador “.

Te invitamos a añadir valor a nuestro contenido informacional aportando tu experiencia en las crónicas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *