试图了解CanActivate和CanActivateChild之间的差异

问题描述 投票:8回答:3

所以,我试图通过使用警卫来保护对多条路线的访问。我正在使用以下路由来执行此操作:

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访问'/ admin'和'/ admin / edit'时(canActivateChild被注释)控制台显示

Guarding...

当我删除canActivateand带canActivateChildback控制台显示

Guarding children...

当我保留两者时,它会回到显示Guarding...。所以,我的问题是当canActivateChildp保护根元素和孩子时,有canActivate的目的是什么?

PS:我知道canActivateChild在子路线被激活之前运行。但那有什么好处呢?是不是只保留其中一个?

angular angular2-guards
3个回答
19
投票

两者都很重要,因为您可能有不同的要求,用户可以访问根组件,但可能不满足子组件的条件。

示例:您可能遇到必须通过身份验证才能导航到根组件的情况,但必须具有权限“x”才能访问子组件。在这种情况下,canActivateChild可以节省大量的打字,因为必须为每个孩子添加canActivate防护。

编辑:

例如,您可能有一个管理模块,其中所有路由都需要防止未经授权的进入:

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

这需要从上到下保护。未经授权访问任何路由,包括root和children。在这种情况下,根级别的canActivate可以很好地保护一切。

但是,您可能还有一些功能模块,其中只需要保护某些孩子:

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

在这种情况下,也许所有用户都需要访问根组件的featureA'和'featureB',但只有某些用户需要能够导航到'featureA'的子路由。在这种情况下,更容易在根级别使用一个防护装置来保护儿童,而不是根本身。另一种方法是将canActivate警卫放在每条儿童路线上,这可能会变得乏味。

这完全取决于你的要求,但有两个选项canActivatecanActivateChild可能会很好。


0
投票

在我看来,CanActivate用于限制从某个路径访问,所有子路径和CanActivateChild用于限制对CanActivate路径内特定组的访问。

例:

{
  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: ...
        }
      ]
    }
  ]
}

因为你需要两种类型的验证,你不能有两个canActivate方法,所以你需要canActivateChild来检查canActivate路径内的permision。显然,你可以创建一个不同的守卫服务(AuthGuardForChildrenRoutes),仍然使用canActivate方法,但这不是重点。


0
投票

在您的示例中,您在canActivateChild中调用了canActivate,因此当您在子路径之间遍历时,两个警卫都会被调用。如果您在两个警卫中都有不同的身份验证逻辑,那么在子路径之间遍历时,您的canActivate警卫将不会执行。

热门问题
推荐问题
最新问题