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

时间:2017-09-13 10:03:24

标签: angular typescript angular-routing angular-router angular-router-guards

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

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

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

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

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

当我从app/home导航到app/contents时,导航两次后只会转到ContentsComponent。因此,如果我执行两次this._router.navigate(['app/components']);它会起作用,如果我只执行一次,则路线从app/home更改为app/route 1ms并返回app/home,如果我第二次这样做,它会改变路线。   然而,如果我在app/contents并尝试导航到app/home,那么就可以改变路线了。

isAuthenticated运行正常。两个authguards工作得很好,所以,如果我在没有登录时尝试访问任何app子路由,我会被重定向到登录,如果我尝试访问login,那么我&#39 ; m登录我被重定向到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;
}

但是,我仍然不理解导航到PreventLoggedInAccess.canActivate孩子时调用app为什么即使附加了AuthGuardService.canActivateChild?为什么只在第一次尝试时调用它?

1 个答案:

答案 0 :(得分:2)

你提到过pageRoute可以拥有app的所有子项 所以它的路由文件应该包含该模块。

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

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

此处页面模块是延迟加载的,只有在authguard返回时才能激活 真正 如果是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

相关问题