2017-10-18 11 views
1

Je me suis récemment coincé avec des gardes angulaires. CanActive s'exécute une seule fois lorsque la page est chargée et ne s'exécute pas lors du changement d'itinéraire dans l'itinéraire protégé. Je pense que cela a été changé parce qu'il fonctionnait à chaque changement. D'après ce que j'ai lu dans les forums, je devrais utiliser CanActivateChild. Le problème est que notre application se compose de plusieurs modules, qui ont plusieurs descendants d'itinéraire et lorsque j'utilise CanActivateChild dans le module racine, il est appelé plusieurs fois lors du changement d'itinéraire. Je trouve qu'il est idiot d'assigner une garde à chaque enfant parce que, pour AppModule, ces modules enfants chargés paresseusement ne devraient être que des 'boîtes noires' et je voulais définir que tous ces modules devraient être gardés.Angulaire: Exécuter canActivate à chaque changement de route

export const routes: Routes = [ 
    { 
    path: '404', 
    component: NotFoundComponent 
    }, 
    { 
    path: '', 
    canActivate: [AuthGuard], 
    component: FullLayoutComponent, 
    data: { 
     title: 'Home' 
    }, 
    children: [ 
     { 
     path: 'administration', 
     loadChildren: './administration/administration.module#AdministrationModule' 
     }, 
     { 
     path: 'settings', 
     loadChildren: './settings/settings.module#SettingsModule' 
     } 
    ] 
    }, 
    { 
    path: '', 
    loadChildren: './account/account.module#AccountModule' 
    }, 
    { 
    path: '**', 
    redirectTo: '404' 
    } 
]; 

Y at-il une solution à cela? Ou trouvez-vous cela comme «pas un problème» en matière de sécurité?

Merci à tous.

Répondre

0

Face au même problème et tout ce que j'ai pu trouver sur le problème sont quelques problèmes fermés sur Github avec des déclarations angular Devs qu'un tel comportement "est par conception".

Alors ce que je fini par faire est vous inscrivant sur les événements de navigation dans app.component et le tir contrôle de AuthGuard là:

constructor(
    private router: Router, 
    private route: ActivatedRoute, 
    private authGuard: AuthGuard, 
) {} 

ngOnInit() { 
    this.router.events 
    .subscribe(event => { 
     if (event instanceof RoutesRecognized) { 
     this.guardRoute(event); 
     } 
    })); 
} 

private guardRoute(event: RoutesRecognized): void { 
    if (this.isPublic(event)) { 
    return; 
    } 

    if (!this.callCanActivate(event, this.authGuard)) { 
    return; 
    } 
} 

private callCanActivate(event: RoutesRecognized, guard: CanActivate) { 
    return guard.canActivate(this.route.snapshot, event.state); 
} 

private isPublic(event: RoutesRecognized) { 
    return event.state.root.firstChild.data.isPublic; 
} 

AuthGuard est plutôt standard:

@Injectable() 
export class AuthGuard implements CanActivate{ 

    constructor(private auth: AuthService, private router: Router) { } 

    canActivate(): Promise<boolean> { 
    return this.auth.isLoggedInPromise() 
     .then(isLoggedIn => { 
     if (!isLoggedIn) { 
      this.router.navigate(["/login"]); 
     } 
     return isLoggedIn; 
     }); 
    } 
    } 

et voies publiques doit être configuré comme ceci:

{ 
    path: "login", 
    component: LoginComponent, 
    data: { isPublic: true } 
} 

Le plus d'une telle mise en œuvre est que chaque chose est protégée par défaut et la route publique doit être configurée explicitement, ce qui réduit la possibilité de laisser certaines routes non protégées. Refactoriser également cela dans un certain type de service, pour pouvoir l'utiliser dans plusieurs applications.

Inspiré par this answer.

+0

Oui, j'ai trouvé exactement la même chose. "Intentionnellement". Je trouve votre réponse comme la meilleure solution jusqu'à présent, alors merci! –