web-dev-qa-db-ja.com

CanActivateとCanActivateChildの違いを理解しようとしています

だから、私は警備員を使っていくつかのルートへのアクセスを保護しようとしています。私はそうするために次のルートを使用しています:

const adminRoutes : Routes = [
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [ AuthGuardService ],
    children : [
      {
        path: '',
        canActivateChild: [ AuthGuardService ],
        children: [
          { path: 'edit', component: DashboardComponent},
          { path: '', component: DashboardComponent}
        ]
      }
    ]
  }
];

AuthGuardServiceがどのように見えるかを見てみましょう

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

@Injectable()
export class AuthGuardService implements CanActivate{

  constructor(private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
    console.log("Guarding...");
    return this.sessionValid();
  }

  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
    console.log("Guarding children...");
    return this.canActivate(route, state);
  }

  sessionValid() : boolean {
    //tests
  }

}

canActivateのみ(canActivateChildがコメント化されている)で「/ admin」および「/ admin/edit」にアクセスしようとすると、コンソールに表示されます

Guarding...

canActivateを削除してcanActivateChildを戻すと、コンソールに表示されます

Guarding children...

両方を保持すると、Guarding...の表示に戻ります。だから、私の質問は、canActivateChildがルート要素と子の両方を保護するときにcanActivateを持つ目的は何ですか?

PS:子ルートがアクティブになる前にcanActivateChildが実行されることがわかりました。しかし、その利点は何ですか?そのうちの1つだけで十分ではありませんか?

11
YounesM

ユーザーがルートコンポーネントにアクセスできる要件が異なる場合がありますが、子コンポーネントの条件を満たしていない可能性があるため、両方が重要です。

例:ルートコンポーネントに移動するにはユーザーを認証する必要があるが、子コンポーネントに移動するには権限「x」が必要な状況が発生する可能性があります。このような場合、canActivateChildを使用すると、各子にcanActivateガードを追加する必要がなくなります。

編集:

たとえば、すべてのルートを不正な侵入から保護する必要がある管理モジュールがあるとします。

  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [ AuthGuardService ],
    children : [
      {
        path: '', component: ...,
      },
      {
        path: 'manage-users', component: ...,
      },
      {
        path: 'manage-roles', component: ...,
      }
    ]
  }

これはトップダウンから保護する必要があります。ルートと子を含むルートへの不正アクセスはありません。この状況では、ルートレベルのcanActivateはすべてを保護するのに最適です。

ただし、特定の子のみを保護する必要がある機能モジュールがある場合もあります。

  {
    path: 'featureA',
    component: ...,
    canActivateChild: [ AuthGuardService ],
    children : [
      {
        path: 'manage-feature', component: ...,
      },
      {
        path: 'manage-members', component: ...,
      }
    ],
    {path: 'featureB', component: ...}
  }

この状況では、すべてのユーザーがルートコンポーネント「featureA」および「featureB」にアクセスする必要があるかもしれませんが、特定のユーザーのみが「featureA」の子ルートに移動できる必要があります。この場合、ルートレベルで1つのガードを使用して子を保護する方が簡単ですが、ルート自体は使用しません。別の方法は、各子ルートにcanActivateガードを配置することです。これは、面倒になる可能性があります。

実際にはすべて要件によって異なりますが、canActivatecanActivateChildの両方のオプションがあると便利です。

19
Tyler Jennings

私の見解では、CanActivateは特定のパスとすべてのサブパスからのアクセスを制限するために使用され、CanActivateChildCanActivate内の特定のグループへのアクセスを制限するために使用されます道。

例:

{
  path: 'admin',
  component: AdminComponent,
  canActivate: [AuthGuardService],
  children : [
    {
      path: 'books', component: ...,
    },
    {
      path: 'authors', component: ...,
    },
    {
      path: 'payments',
      canActivateChild: [AuthGuardService],
      children: [
        {
          path: 'list', component: ...
        },
        {
          path: 'list/:id', component: ...
        }
      ]
    }
  ]
}

2種類の検証が必要なため、2つのcanActivateメソッドを持つことはできません。したがって、canActivateChildパス内の権限をチェックするためにcanActivateが必要です。明らかに、別のガードサービス(AuthGuardForChildrenRoutes)を作成し、それでもcanActivateメソッドを使用できますが、それは重要ではありません。

1
Marius Lazar

あなたの例では、canActivateChild内でcanActivateを呼び出したため、子ルート間を移動するときに両方のガードが呼び出されます。両方のガード内に異なる認証ロジックがある場合、子ルート間を移動している間、canActivateガードは実行されません。

0
Akshay D