具有无组件路由的 CanActivate 与 CanActivateChild
Posted
技术标签:
【中文标题】具有无组件路由的 CanActivate 与 CanActivateChild【英文标题】:CanActivate vs. CanActivateChild with component-less routes 【发布时间】:2017-03-02 23:31:23 【问题描述】:关于 Route Guards 的 angular2 文档让我不清楚何时将 CanActivate
防护与 CanActivateChild
防护与无组件路由结合使用。
TL;DR:当我可以使用带有canActivate
的无组件路由来实现相同效果时,拥有canActivateChild
有什么意义?
长版:
我们可以在路由层次结构的每一层都有多个警卫。这 路由器首先检查 CanDeactivate 和 CanActivateChild 守卫, 从最深的子路径到顶部。然后它检查 CanActivate 从上到下保护最深的子路线。
我知道CanActivateChild
是自下而上检查的,CanActivate
是自上而下检查的。对我来说没有意义的是文档中给出的以下示例:
@NgModule(
imports: [
RouterModule.forChild([
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
children: [
path: '',
canActivateChild: [AuthGuard],
children: [
path: 'crises', component: ManageCrisesComponent ,
path: 'heroes', component: ManageHeroesComponent ,
path: '', component: AdminDashboardComponent
]
]
])
],
exports: [
RouterModule
]
)
export class AdminRoutingModule
所以admin
路径有一个无组件路由:
查看AdminComponent下的子路由,我们有一个路由 带有路径和子属性,但它没有使用组件。我们 我们的配置没有出错,因为我们可以使用 无组件路由。
为什么这种情况下的代码在子组件和根组件(路径admin
)中插入AuthGuard
?从根本上守卫还不够吗?
我根据删除canActivateChild: [AuthGuard]
并在AdminDashboard
上添加注销按钮的示例创建了plunkr。果然,父路由的canActivate
仍然守卫,那么当我可以将无组件路由与canActivate
一起使用时,拥有canActivateChild
有什么意义呢?
【问题讨论】:
我想知道同样的事情,你有机会在 github 上发布这个吗? 这是同一个问题,也许对你有帮助:***.com/questions/42632154/… 我认为您仍然可以在根admin
路径上拥有一个 canActivateChild
,这样您就不需要无组件路由。我相信这里的无组件方法在指南中被用来证明我们甚至可以更进一步,对相关的子路由进行分组,以便对它们应用更专业的防护。
【参考方案1】:
From the docs:
当我们了解了使用 CanActivate 保护路由时,我们还可以使用 CanActivateChild 保护来保护子路由。 CanActivateChild 守卫与 CanActivate 守卫类似,但不同之处在于它在每个子路由被激活之前运行。我们保护我们的管理功能模块免受未经授权的访问,但我们也可以保护我们的功能模块中的子路由。
这是一个实际的例子:
-
导航到
/admin
canActivate
被选中
您在/admin
路由的子节点之间导航,但不会调用canActivate
,因为它保护/admin
canActivateChild
在其定义的路由的子级之间发生变化时被调用。
希望对你有所帮助,如果还不清楚,可以通过添加警卫调试来检查具体功能。
【讨论】:
但为什么不直接将 AuthGuard 作为 CanActivateChild 放在 AdminComponent 上。我不明白添加额外的无组件路由有什么好处? 我猜它会在以后的框架中以某种方式改变。总有更简单的解决方案。【参考方案2】:在现实世界中,我觉得为父母及其所有孩子使用同一个警卫是多余的。
举个更好的例子,假设您有管理员用户的角色(编辑/查看),您可以为仅“编辑”选项卡添加保护。
RouterModule.forChild([
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard], //1 - redirect to login page if not logged in
children: [
//View Access
......
,
//Edit Access
path: '',
canActivateChild: [EditGuard], //2 - display "you don't have Edit permission to access this page"
children: [
path: 'crises', component: ManageCrisesComponent ,
path: 'heroes', component: ManageHeroesComponent ,
path: '', component: AdminDashboardComponent
]
]
])
【讨论】:
【参考方案3】:我也混淆了 angular2 关于 routeGuard 的文档。
CanActivate
防护和有什么区别
CanActivateChild
守卫。
我有一些发现,希望对你有帮助。
在auth-guard.service.ts
文件中
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean
let url: string = state.url;
return this.checkLogin(url);
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean
return this.canActivate(route, state);
因为在canActivateChild
函数中调用了canActivate
方法。您可以编写一段不调用canActivate
方法的sn-p 代码在canActivateChild
函数中。
【讨论】:
【参考方案4】:我能想到的一个原因是超时。
我开始使用 Angular 2,使用身份验证提供程序。此提供程序使闲置超过一定时间的会话到期。
在您让计算机保持登录状态并且会话过期的常见情况下,您尝试的下一次导航必须验证您当前的情况。如果您在子路由之间导航,我认为CanActivateChild
是检测过期会话并触发重定向登录的守卫,而CanActivate
根本不会触发。
免责声明:这是我的想法,我还没有实现它。
【讨论】:
【参考方案5】:如果定义了 10 个孩子会怎样。
那么canActivateChild
只需要在他们都有共同要求的情况下进入一个地方,而不是每个孩子有 10 个canActivate
。
【讨论】:
您仍然可以在无组件路由上使用canActivate
。【参考方案6】:
TL;DR: CanActivate
和 CanActivateChild
不适用于无组件路由。
我相信文档只是忽略了无组件路线中两个守卫的必要性,因为其目的只是为了在文档的特定里程碑中展示无组件路线以及两个守卫在另一个。
在特定场景中使用这两种保护非常有用,例如:
允许登录查看多个组件的管理仪表板,如邮件、日志统计、资源使用等 - 在此级别,访问受到 CanActivate
守卫的限制 - 当尝试导航到每个组件时,每个管理员用户的角色是由CanActivateChild
守卫检查。
【讨论】:
以上是关于具有无组件路由的 CanActivate 与 CanActivateChild的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2 - 路由 - CanActivate 与 Observable 一起工作
Angular 2 路由已弃用:如何检测 CanActivate?
为啥路由保护 canLoad 不会触发,但 canActivate 会
如何在 Angular 中为所有路由(主路由和所有子路由)应用 canActivate 保护