问题
I have a angular2 active guard which handle if the user is not logged in, redirect it to login page:
import { Injectable } from "@angular/core";
import { CanActivate , ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {Observable} from "rxjs";
import {TokenService} from "./token.service";
@Injectable()
export class AuthenticationGuard implements CanActivate {
constructor (
private router : Router,
private token : TokenService
) { }
/**
* Check if the user is logged in before calling http
*
* @param route
* @param state
* @returns {boolean}
*/
canActivate (
route : ActivatedRouteSnapshot,
state : RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
if(this.token.isLoggedIn()){
return true;
}
this.router.navigate(['/login'],{ queryParams: { returnUrl: state.url }});
return;
}
}
I have to implement it on each route like :
const routes: Routes = [
{ path : '', component: UsersListComponent, canActivate:[AuthenticationGuard] },
{ path : 'add', component : AddComponent, canActivate:[AuthenticationGuard]},
{ path : ':id', component: UserShowComponent },
{ path : 'delete/:id', component : DeleteComponent, canActivate:[AuthenticationGuard] },
{ path : 'ban/:id', component : BanComponent, canActivate:[AuthenticationGuard] },
{ path : 'edit/:id', component : EditComponent, canActivate:[AuthenticationGuard] }
];
Is there any better way to implement canActive option without adding it to each path.
What I want is to add it on main route, and it should apply to all other routes. I have searched alot, but I could not find any useful solution
Thanks
回答1:
You can introduce a componentless parent route and apply the guard there:
const routes: Routes = [
{path: '', canActivate:[AuthenticationGuard], children: [
{ path : '', component: UsersListComponent },
{ path : 'add', component : AddComponent},
{ path : ':id', component: UserShowComponent },
{ path : 'delete/:id', component : DeleteComponent },
{ path : 'ban/:id', component : BanComponent },
{ path : 'edit/:id', component : EditComponent }
]}
];
回答2:
You can also subscribe to the router's route changes in your app.component's ngOnInit function and check authentication from there e.g.
this.router.events.subscribe(event => {
if (event instanceof NavigationStart && !this.token.isLoggedIn()) {
this.router.navigate(['/login'],{ queryParams: { returnUrl: state.url}});
}
});
I prefer this way of doing any kind of app wide check(s) when a route changes.
回答3:
I think you should implement "child routing" which allow you to have a parent (with a path "admin" for example) and his childs.
Then you can apply a canactivate to the parent which will automatically restrict the access to all his child. For example if I want to access "admin/home" I'll need to go throught "admin" which is protectected by canActivate. You can even define a parent with an empty path "" if you want
回答4:
I came across this example when searching and was caught out by the example given in the example.
You need to ensure that the guard returns true if you want to show the child routes.
@Injectable()
export class AuthenticationGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthService) { }
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
// Auth checking code here
// Make sure you return true here if you want to show child routes
return true;
}
}
来源:https://stackoverflow.com/questions/43487827/how-to-apply-canactivate-guard-on-all-the-routes