Маршруты Охранники, вызывающие неправильное поведение навигации по маршруту
У меня проблема с навигацией по различным маршрутам.
У меня есть два разных модуля маршрута.
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
prefix и дочерним маршрутом 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
на 1 мс, и он возвращается в app/home
, а если я делаю это во второй раз, он меняет маршрут. Хотя, если я в app/contents
и пытаюсь перейти к app/home
он меняет маршрут просто отлично.
isAuthenticated
работает отлично. Оба authguards работают очень хорошо, поэтому, если я пытаюсь получить доступ к любому дочернему маршруту app
когда я не зарегистрирован, я получаю перенаправление для входа в систему и если я пытаюсь получить доступ к login
при 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;
}
Но все же я не понимаю, почему PreventLoggedInAccess.canActivate
вызывается при навигации по дочернему app
хотя к AuthGuardService.canActivateChild
прикреплен AuthGuardService.canActivateChild
? Почему он называется только с первой попытки?
Ответы
Ответ 1
Вы упомянули, что pageRoute может иметь все дочерние приложения, поэтому файл маршрутизации должен содержать этот модуль.
Таким образом, можно легко использовать концепцию ленивой загрузки и защиты. Я ответил на это, предположив, что ваш модуль pageRoute является дочерним элементом приложения.
Я предлагаю использовать AuthGuard только один раз. AuthGaurd следует использовать на модуле, содержащем другие модули или компоненты, а не быть самим компонентом входа.
Здесь модуль страницы загружен и может быть активирован только в том случае, если authguard возвращает true. В случае, если ложный пользователь будет перемещаться для входа в систему.
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 },
]
}
];
Если вы хотите отлаживать текущее условие маршрутизации, вы можете использовать Augury из интернет-магазина Chrome.