【问题标题】:Router infinite loop with second canActivate guard on lazy-loaded modules延迟加载模块上带有第二个 canActivate 保护的路由器无限循环
【发布时间】:2018-02-13 23:11:48
【问题描述】:

我有一个带有延迟加载模块的 Angular 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

  1. NavigationStart(id: 4, url: '/password/set')
  2. RoutesRecognized {id: 4, url: "/password/set", urlAfterRedirects: "/password/set", state: RouterStateSnapshot}
  3. GuardsCheckStart {id: 4, url: "/password/set", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
  4. GuardsCheckEnd {id: 4, url: "/password/set", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, shouldActivate: true}
  5. NavigationCancel {id: 4, url: "/password/set", 原因: ""}

然后这个循环会重复。

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

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

问题:

  1. 既然模块是延迟加载的,我在路由器或守卫中做错了什么以强制执行此循环?我对shouldActivate: true 后跟NavigationCancel reason: "" 感到特别困惑。

  2. 这是否与我直接在 AuthenticationGuard 中重定向这一事实有关,现在这个保护应用于我的主要空根路由 ({ path: '', redirectTo: 'fleet', pathMatch: 'full' }) 它总是被调用并重定向,甚至一旦我设置了路径?

  3. 我真的需要在子路由和根路由中重复canActivate 守卫吗?

  4. 像往常一样,欢迎任何其他 cmets。

【问题讨论】:

    标签: angular lazy-loading angular-router angular-router-guards


    【解决方案1】:

    问题是我过度应用了AuthenticationGuard:它不应该应用到顶级 AppComponent,因为它总是会重定向到选择新密码模块,即使它正在加载该模块。

    我的根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 模式。)

    【讨论】:

    • 所以 'password/set' 不必由 AuthenticationGuard 保护?
    • @AnjilDhamala 正确,如您所见,它有自己的守卫,它重新实现了AuthenticationGuard 的一些逻辑,但只允许您访问一条路线。
    • 感谢您回来。我实际上发现我的 ngrx 设置有问题。我陷入了状态变化地狱,登录页面订阅了状态变化并在状态返回重定向 url 时重定向到某个页面。不幸的是,导航取消了警戒检查,我试图深度链接的页面进行了另一个 ngrx 操作调用,该调用不断更改状态,而我的登录页面一直试图对更改做出反应。因此,我的浏览器崩溃了。
    • @AnjilDhamala 啊,您的情况可能需要注意的是,我们的登录页面实际上位于 Angular 应用程序之外,由 JBoss 提供服务,然后重定向到 Angular。我们的整个 Angular 应用程序都需要身份验证。不过,你读起来很好!我相信你现在可以发布一个关于它的问题。
    • 看起来它也适用于父级的 AuthGuard,但您必须在 AuthGurad 中使用返回的 urltree。让它像那样工作。看看这个:juristr.com/blog/2018/11/better-route-guard-redirects/…
    猜你喜欢
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2017-08-21
    • 2021-08-06
    • 2019-04-03
    相关资源
    最近更新 更多