【问题标题】:Angular 2 Router Guards orderAngular 2 Router Guards 订单
【发布时间】:2018-01-18 23:55:12
【问题描述】:

Angular 2 路由器防护可以在数组中定义。例如:

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

以下是我的问题:

  1. 两名守卫的执行顺序是什么。
  2. 如果我只想在 CanAlwaysActivateGuard 返回 true 时执行 AuthGuard,这可能吗。

【问题讨论】:

    标签: angular angular2-routing


    【解决方案1】:

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

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

    在任何内部路由防护之前评估外部路由防护。

    【讨论】:

      【解决方案2】:

      对于当前版本,可以使用子路由器,例如:

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

      【讨论】:

        【解决方案3】:

        您还可以在 AuthGuard.canActivate() 之前继承保护运行 super.canActivate()

        在此示例中,两个类中的canActivate() 方法都返回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,因为canActivate 守卫在canActivateChild 之前运行。

        【讨论】:

          【解决方案4】:

          我遇到了这个问题,并在寻找答案时遇到了您的帖子。没有找到——今天有时间——我想出了一个我认为你可能会感兴趣的解决方案。我创建了一个“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”。

          现在我的路由守卫以“and”语义“按顺序”运行(所有路由都必须成功才能激活)。

          【讨论】:

          • 由于injector.get(...)已被弃用,最好使用这个:const routeGuard = this.injector.get&lt;CanActivate&gt;(routeGuards[i]);
          【解决方案5】:

          两名守卫的执行顺序是什么。

          它们将同步运行,无需相互等待。

          如果我只想在 CanAlwaysActivateGuard 返回时执行 AuthGuard 是的,这可能吗?

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

          另见How to wait for guards in Angular

          【讨论】:

          • 它们是否按照定义的顺序同步运行?还是随机的?对于在没有异步操作的情况下解析的守卫,您可能不必担心等待。
          • 我记得,它们按照定义的顺序运行,但我不确定。
          猜你喜欢
          • 2017-10-21
          • 2016-11-24
          • 2019-05-19
          • 1970-01-01
          • 2016-10-09
          • 1970-01-01
          • 2023-03-21
          • 2017-10-09
          • 1970-01-01
          相关资源
          最近更新 更多