首页 文章

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

提问于
浏览
12

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

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

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 });

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

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

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);

如果用户不是't logged in. It',则后者会重定向到 /login

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

当我从app / home导航到app / contents时,它只会在导航两次后转到ContentsComponent . 所以,如果我这样做两次._router.navigate(['app / components']);它工作,如果我只做一次,路线从app / home变为app / route 1ms并返回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 被调用

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

EDIT

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

canActivate(): boolean {
  if (!this._authService.isAuthenticated()) {
      return true;
  }
  return false;
}

但是,我还是不明白 why PreventLoggedInAccess.canActivate is called when navigating to an app child even though AuthGuardService.canActivateChild is attached to it? Why is it called only on the first attempt?

1 回答

  • 2

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

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

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

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

    app.route.ts

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

    AuthGuard

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

    Page.route.ts

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

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

相关问题