路由守卫导致错误的路由导航行为
Routes Guards causing wrong Route Navigation behavior
我在尝试浏览不同路线时遇到问题。
我有两个不同的路由模块。
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;
}
When I navigate from app/home
to app/contents
it only goes to ContentsComponent
after navigating two times. So, if I do two times this._router.navigate(['app/components']);
it works, if I do it only one time, the route changes from app/home
to app/route
for 1ms and it returns to app/home
, while if I do it a second time it changes route.
While, if I'm in app/contents
and try to navigate to app/home
it changes route just fine.
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
被称为
当然是第二种行为。
编辑
从 PreventLoggedInAccess.canActivate
中删除 this._router.navigate([/app/home]);
解决了问题
canActivate(): boolean {
if (!this._authService.isAuthenticated()) {
return true;
}
return false;
}
但是,我仍然不明白 为什么在导航到 app
子级时调用 PreventLoggedInAccess.canActivate
,即使 AuthGuardService.canActivateChild
已附加到它?为什么只在第一次尝试时调用它?
您提到 pageRoute 可以拥有应用程序的所有子子项
所以它的路由文件应该包含那个模块。
因此可以正确使用延迟加载和守卫的概念。
我通过假设您的 pageRoute 模块是 App.
的子模块来回答这个问题
我建议只使用一次AuthGuard。 AuthGaurd 应该在包含其他模块或组件的模块上使用,而不是在登录组件本身上使用。
这里页面模块是懒加载的,需要authguard才能激活returns
真的
如果是假用户,将导航到登录。
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。
我在尝试浏览不同路线时遇到问题。
我有两个不同的路由模块。
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;
}
When I navigate from
app/home
toapp/contents
it only goes toContentsComponent
after navigating two times. So, if I do two timesthis._router.navigate(['app/components']);
it works, if I do it only one time, the route changes fromapp/home
toapp/route
for 1ms and it returns toapp/home
, while if I do it a second time it changes route. While, if I'm inapp/contents
and try to navigate toapp/home
it changes route just fine.
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
被称为
当然是第二种行为。
编辑
从 PreventLoggedInAccess.canActivate
中删除 this._router.navigate([/app/home]);
解决了问题
canActivate(): boolean {
if (!this._authService.isAuthenticated()) {
return true;
}
return false;
}
但是,我仍然不明白 为什么在导航到 app
子级时调用 PreventLoggedInAccess.canActivate
,即使 AuthGuardService.canActivateChild
已附加到它?为什么只在第一次尝试时调用它?
您提到 pageRoute 可以拥有应用程序的所有子子项 所以它的路由文件应该包含那个模块。
因此可以正确使用延迟加载和守卫的概念。 我通过假设您的 pageRoute 模块是 App.
的子模块来回答这个问题我建议只使用一次AuthGuard。 AuthGaurd 应该在包含其他模块或组件的模块上使用,而不是在登录组件本身上使用。
这里页面模块是懒加载的,需要authguard才能激活returns 真的 如果是假用户,将导航到登录。
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。