Angular 2 Router Guards 命令

Angular 2 Router Guards order

Angular一个数组可以定义2个router guards。例如:

<code>
 canActivate: ['CanAlwaysActivateGuard','AuthGuard']
</code>

以下是我的问题:

  1. 两名守卫的执行顺序是什么。
  2. 如果我只想在 CanAlwaysActivateGuard returns 为真时执行 AuthGuard,这是否可能。

what will be the order of execution for both the guards.

它们将运行同步,无需等待对方。

if i want to execute AuthGuard only if CanAlwaysActivateGuard returns true, would that be possible.

不,当前的实现不可能。作为解决方法,您可以按顺序为 运行 您的守卫创建一个包装守卫。

另请参阅此

我遇到了这个问题,在寻找答案时遇到了您的 post。找到 none——今天有时间——我想出了一个你可能感兴趣的解决方案。我创建了一个 "CompositeRouteGuard":

import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import {Injectable, Injector} from '@angular/core';
import { Observable } from "rxjs";

@Injectable()
export class CompositeRouteGuard implements CanActivate {

  constructor(  protected router: Router,
                protected injector: Injector ) {
  }

  canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> {
    var compositeCanActivateObservable: Observable<boolean> = Observable.of(true);

    let routeGuards = route.data.routeGuards;

    if(routeGuards){
      for( var i = 0; i < routeGuards.length; i++ ){
        let routeGuard = this.injector.get(routeGuards[i]);
        let canActivateObservable = routeGuard.canActivate(route, state);
        compositeCanActivateObservable = compositeCanActivateObservable.flatMap( (bool) => {
          if(!bool){
            return Observable.of(false);
          }
          else{
            return canActivateObservable;
          }
        });
      }
    }

    return compositeCanActivateObservable;
  }
}

这需要在您的 routes.ts 中进行一些额外的配置。您需要在路由的数据元素中添加一个 "routeGuards" 数组。

const routes: Routes = [
  {
    path: '...',
    component: AComponent,
    data: { routeGuards: [ FooRouteGuard, BarRouteGuard, BazRouteGuard ] },
    canActivate: [ CompositeRouteGuard ]
  },
...

我只关心 canActivate 操作,但您应该能够轻松扩展它,例如 "canDeactivate"(例如)如果您需要的话。

现在我的路由守卫 运行 "in order" 具有 "and" 语义(所有都必须成功才能激活路由)。

当前版本可以使用child router,例如:

{
    path: 'your-path',
    canActivate: [
        CanAlwaysActivateGuard,
    ],
    canActivateChild: [
        AuthGuard,
    ],
    children: [
    ]
}

你也可以在AuthGuard.canActivate()之前继承守卫运行super.canActivate()

In this example canActivate() method in both classes returns a Promise.

@Injectable({
  providedIn: 'root',
})
class AuthGuard extends CanAlwaysActivateGuard implements CanActivate {
  constructor(/*...*/) {
    super(/*...*/);
  }

  async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree> {
    const result = await super.canActivate(next, state);

    if (result === true) { // Check the expected result from the parent
        return await this.logicOfYourAuthGuard(); // Run your logic and return it
    }

    return result; // Return the original result if logic of AuthGuard is not nedded
  }
}

然后,在路线中,只使用AuthGuard


其他选项是使用 canActivateChild,因为 canActivatecanActivateChild.

之前守卫 运行s

如果你嵌套它们,你可以决定它们的顺序:

import { Routes } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    canActivate: [CanAlwaysActivateGuard],
    children: [
      {
        path: '',
        canActivate: [AuthGuard],
        children: [
          // (...)
        ],
      }
    ],
  }
];

在任何内部路由守卫之前评估外部路由守卫。