2017-03-06 39 views
2

因此,我试图通过使用警卫来保护对几条路线的访问。我使用以下途径可以这样做:试图了解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 
    } 

} 

当我尝试进入“/管理员”和“/管理/编辑”只有canActivatecanActivateChild被注释掉)的控制台显示

Guarding... 

当我删除canActivate,并把canActivateChild回控制台DISPLA ys

Guarding children... 

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

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

回答

6

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

示例:您可能遇到以下情况:用户必须通过身份验证才能导航到根组件,但必须具有权限“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'的子路由。在这种情况下,在根级别使用一名警卫人员更容易保护儿童,但不是根本身。另一种方法是在每条儿童路线上放置canActivate警卫,这可能会很乏味。

这一切都取决于您的要求,但它可以很好同时具有canActivatecanActivateChild的选项。

+0

我们不能只使用canActivate而不是canActivateChild吗? – YounesM

+2

也许,这取决于您的要求。我上面给出的例子可能有点太过于人为设计。 'canActivateChild'在每个子路由被激活之前运行。你确实可以使用'canActivate'来保护一个所有孩子的根组件,但是你可能有孩子,某些用户不需要查看他们何时需要能够看到根组件。例如,您可以将一些管理组件中的数据添加到大多数或所有用户需要到达根目录的Feature模块中,但不一定是某些路由的子模块。 –

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方法,但那不是重点。