路线防护导致错误的路线导航行为

And*_*M16 12 typescript angular-routing angular angular-router-guards angular-router

我在尝试浏览不同的路线时遇到了问题.

我有两个不同的路线模块.

app.routes.ts:

仅包含LoginPage:

export const routes: Routes = [
  {
    path: 'login',
    component: LoginPageComponent,
    canActivate: [PreventLoggedInAccess]
  },
  {
    path: '',
    redirectTo: 'login',
    pathMatch: 'full'
  },
  {
    path: '**',
    redirectTo: 'login'
  }
];

export const Routing: ModuleWithProviders = 
    RouterModule.forRoot(routes, { useHash : true });
Run Code Online (Sandbox Code Playgroud)

使用PreventLoggedInAccess.canActivate,如果用户已经登录,则将其重定向到具有/app前缀和子路由的登录部分home.它被定义为:

canActivate(): boolean {
  if (!this._authService.isAuthenticated()) {
      return true;
  }
  this._router.navigate(['/app/home']);
  return false;
}
Run Code Online (Sandbox Code Playgroud)

pages.routes.ts:

包含/app仅在用户登录时才可访问的所有子路由.这可以通过以下方式实现AuthGuardService.canActivateChild:

export const pageRoutes: Routes = [
  {
    path: 'app',
    component: PagesComponent,
    canActivateChild: [AuthGuardService],
    children: [
      { path: '', redirectTo: 'home', pathMatch: 'full' },
      { path: 'home', component: HomePageComponent },
      { path: 'contents', component: ContentsComponent },
    ]
  }
];

export const Routing: ModuleWithProviders = RouterModule.forChild(pageRoutes);
Run Code Online (Sandbox Code Playgroud)

/login如果用户没有登录,后者会重定向到.它被定义为:

canActivateChild(): boolean {
  if (this._authService.isAuthenticated()) {
      return true;
  }
  this._router.navigate(['login']);
  return false;
}
Run Code Online (Sandbox Code Playgroud)

当我从导航app/home到导航时app/contents,仅ContentsComponent导航两次.所以,如果我做两次this._router.navigate(['app/components']);它的工作原理,如果我这样做,只是一个时间,从路线的变化app/home,以app/route1毫秒并将其返回到app/home,而如果我去做了第二次它改变路线.然而,如果我在app/contents并尝试导航到app/home它改变路线就好了.

isAuthenticated工作良好.两个authguards工作得很好,所以,如果我app在没有登录时尝试访问任何子路由,我会被重定向到登录,如果login我在登录时尝试访问,我会被重定向到app/home.

我设法调试了一下,我注意到以下流程:

  • 第一次尝试 - app/home- > app/contents:
    • navigate(['app/contents']) 叫做
    • PreventLoggedInAccess.canActivate 叫做
    • AuthGuardService.canActivateChild 叫做
  • 第二次尝试 - app/home- > app/contents:
    • navigate(['app/contents']) 叫做
    • AuthGuardService.canActivateChild 叫做

当然,预期的行为是第二​​个.

编辑

删除this._router.navigate([/app/home]);PreventLoggedInAccess.canActivate解决问题

canActivate(): boolean {
  if (!this._authService.isAuthenticated()) {
      return true;
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)

但是,我仍然不明白为什么PreventLoggedInAccess.canActivate在导航到一个app孩子的时候被调用,即使AuthGuardService.canActivateChild它附在它上面?为什么只在第一次尝试时调用?

Raj*_*pta 2

您已经提到 pageRoute 可以拥有应用程序的所有子子项,因此其路由文件应包含该模块。

因此可以正确使用延迟加载和防护的概念。我通过假设您的 pageRoute 模块是 App 的子模块来回答这个问题。

我建议仅使用 AuthGuard 一次。AuthGaurd 应该在包含其他模块或组件的模块上使用,而不是在登录组件本身上使用。

这里的页面模块是延迟加载的,只有当 authguard 返回 true 时才能激活,否则用户将导航到登录。

应用程序.route.ts

const routes: Routes = [
  {
    path: '',
    loadChildren: './pages/pages.module#PagesModule',
    canActivate: [AuthGuardService]
  },
  { path: 'login', loadChildren: './login/login.module#LoginModule' },

];
Run Code Online (Sandbox Code Playgroud)

验证卫士

canActivateChild(): boolean {
  if (this._authService.isAuthenticated()) {
      return true;
  }
  this._router.navigate(['/login']);
  return false;
}
Run Code Online (Sandbox Code Playgroud)

页面.route.ts

const routes: Routes = [
  {
    path: '', component: PageComponent,
     children: [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: HomePageComponent },
  { path: 'contents', component: ContentsComponent },


     ]
  }
];
Run Code Online (Sandbox Code Playgroud)

如果您想在当前路由条件下进行调试,您可以使用Chrome 网上商店中的Augury 。