Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
759 views
in Technique[技术] by (71.8m points)

angular - Multiple canActivate guards all run when first fails

I have a route with two canActivate guards (AuthGuard and RoleGuard). The first (AuthGuard) checks to see if the user is logged in and, if not, redirects to the login page. The second checks to see if the user has a role defined that is allowed to view the page and, if not, redirects to the un-authorized page.

canActivate: [ AuthGuard, RoleGuard ]
...
export class AuthGuard implements CanActivate {
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        ...
        this.router.navigate(['/login']);
        resolve(false);
}

export class RoleGuard implements CanActivate {
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
        ...
        this.router.navigate(['/unauthorized']);
        resolve(false);
}

The problem is that when I access the route and I am not logged in I hit the AuthGuard, which fails and tells the router to navigate to /login. However, even though the AuthGuard failed, the RoleGuard runs anyway which then navigates to /unauthorized.

In my opinion it is pointless to run the next guard if the first fails. Is there any way to enforce this behavior?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is due to the fact you are returning a Promise<boolean> instead of just a boolean. If you were to just return a boolean it wouldn't check the RoleGuard. I would guess this is either a bug in angular2 or an expected result of async requests.

You can however resolve this with your example by only using RoleGuard for urls where a certain Role is required, because I guess you need to be logged in to have a role. In that case you can change your RoleGuard to this:

@Injectable()
export class RoleGuard implements CanActivate {
  constructor(private _authGuard: AuthGuard) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    return this._authGuard.canActivate(route, state).then((auth: boolean) => {
      if(!auth) {
        return false;
      }
      //... your role guard check code goes here
    });
  }
}

Update
In the latest Angular version (currently v8.x) - Even if both Guard will return false - they will still be both executed. (behavior was aligned between different return values)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...