首页 文章

路由器无限循环,第二个canActivate防守延迟加载模块

提问于
浏览
1

我有一个带有延迟加载模块的角度4.3.6应用程序 . 这是一个部分根路由器:

const routes: Routes = [
  { path: '', redirectTo: 'fleet', pathMatch: 'full' },
  {
    path: '',
    component: AppComponent,
    canActivate: [AuthenticationGuard],
    children: [
      {
        path: 'fleet',
        loadChildren: "./modules/fleet.module",
        canActivate: [AuthenticationGuard]
      },
      {
        path: 'password/set',
        loadChildren: "./modules/chooseNewPassword.module",
        canActivate: [ChoosePasswordGuard]
      }
    ]
  }
]
// Exports RouterModule.forRoot(routes, { enableTracing: true });

我的子路由器在这两个示例模块中:

舰队:

RouterModule.forChild([
  {
    path: '',
    component: FleetComponent,
    canActivate: [AuthenticationGuard]
  }
]);

选择新密码:

RouterModule.forChild([
  {
    path: '',
    component: ChooseNewPasswordComponent,
    canActivate: [ChoosePasswordGuard]
  }
]);

AuthenticationGuard 调用一个如下所示的方法:

return this.getUserSession().map((userSession: UserSession) => {
  if (userSession && userSession.ok) {
    return true;
  }
  else if (userSession && userSession.expired) {
    this.router.navigate(['password/set'])
      .catch((e: Error) => console.error(e));
    return true;
  }
  else {
    window.location.replace('/');
    return false;
  }
}

因此,如果用户的会话正常,则会激活路由 . 如果用户的密码已过期,则会将用户重定向到选择新密码模块 . 如果没有会话,则重定向到登录 .

ChoosePasswordGuard 做了类似的事情,但只保护选择新密码组件(一般使用不同的工具来设置密码):

return this.getUserSession().map((userSession: UserSession) => {
  if (userSession) {
    return userSession.expired;
  }
  else {
    return false;
  }
});

这在模块拆分之前有效 .

现在,我陷入了重定向循环 . 在路由器跟踪的情况下,我会观察以下顺序 . 用户登录并 AuthenticationGuard 更正重定向到/ password / set模块,并切换到 ChooseNewPasswordGuard

  • NavigationStart(id:4,url:'/password/set')

  • RoutesRecognized {id:4,url:"/password/set",urlAfterRedirects:"/password/set",state:RouterStateSnapshot}

  • GuardsCheckStart {id:4,url:"/password/set",urlAfterRedirects:UrlTree,state:RouterStateSnapshot}

  • GuardsCheckEnd {id:4,url:"/password/set",urlAfterRedirects:UrlTree,state:RouterStateSnapshot, shouldActivate: true }

  • NavigationCancel {id:4,url:"/password/set", reason: "" }

并且这个循环重复 .

(如果我用 return Observable.of(true); 替换整个ChooseNewPasswordGuard,它也会重复)

编辑:即使我在URL栏中提供 /#/password/set ,我也被重定向到根页面( / )...

Questions:

  • 由于模块是延迟加载的,我在路由器或防护装置中做错了什么来强制执行此循环?我特别感到困惑的是 shouldActivate: true ,接着是 NavigationCancel reason: "" .

  • 这是否与我直接在AuthenticationGuard中重定向的事实有关,现在这个防护应用于我的主空根路径( { path: '', redirectTo: 'fleet', pathMatch: 'full' } )它's always called and redirects, even once I'已设置路径?

  • 我是否真的需要在我的子路线和我的根路线中重复 canActivate 守卫?

  • 像往常一样,欢迎提出任何其他意见 .

1 回答

  • 2

    问题是我过度应用 AuthenticationGuard :它不应该应用于顶级AppComponent,因为它总是会重定向到Choose New Password模块,即使它正在加载该模块 .

    我的根 routes 应该是这样的:

    const routes: Routes = [
      { path: '', redirectTo: 'fleet', pathMatch: 'full' },
      {
        path: '',
        component: AppComponent,
        // canActivate: [AuthenticationGuard], // <-- Remove this guard
        children: [
          {
            path: 'fleet',
            loadChildren: "./modules/fleet.module",
            canActivate: [AuthenticationGuard]
          },
          {
            path: 'password/set',
            loadChildren: "./modules/chooseNewPassword.module",
            canActivate: [ChoosePasswordGuard]
          }
        ]
      }
    ]
    

    (我欢迎并乐意接受更好的解释或更好的AuthenticationGuard模式 . )

相关问题