Angular路由器激活了错误的路由保护
Angular router activates wrong route guard
我遇到了 Angular 似乎没有多大意义的路由问题。通过以下设置,会出现此结果...
- 应用加载路径
/
- Auth guard 运行s
- Auth guard returns false 因为存储中还没有 JWT
- 重定向到
/login
按预期工作。
然而...
- 直接导航到
/activate
(帐户模块中的路由)
- 控制台记录身份验证守卫 运行(这不应该发生)
- 重定向到
/login
我很难理解为什么 auth guard 运行宁 /activate
路由不是仪表板布局的子路由。
应用程序路由
{
path: '',
component: DashboardLayoutComponent,
canActivate: [AuthGuard],
canActivateChild: [DashboardGuard],
children: [
{
path: 'schedule',
loadChildren: () =>
import('@libs/schedule').then(
i => i.ScheduleModule
),
data: {
breadcrumb: 'Schedule'
}
},
// Other feature modules omitted
{
path: '',
redirectTo: '/schedule',
pathMatch: 'full'
}
]
}
账户路由
{ path: 'login', component: LoginComponent },
{ path: 'activate', component: ActivateComponent }
Auth Guard
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private jwtService: JwtService,
private router: Router,
private accountService: accountService
) { }
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
console.log('Auth Guard Start'); // <-- This appears in console
return this.jwtService.getToken().pipe(
map(token => {
if (!token) {
this.router.navigate(['/login']);
return false;
}
// Attempt to populate the user using the token.
this.accountService.populate();
return true;
}),
take(1)
);
}
}
应用模块
@NgModule({
declarations: [AppComponent, DashboardLayoutComponent],
imports: [
// .. other modules omitted
AccountModule,
AppRoutingModule
],
providers: [AuthGuard, DashboardGuard],
bootstrap: [AppComponent]
})
export class AppModule { }
附加信息
这仅在 运行 处于生产模式时发生。
Augury 报告说 /login
和 /activate
都是 /
路线的兄弟姐妹。 https://imgur.com/a/CJyKu8C
@angular/core: 8.2.6
@angular/router: 8.2.6
其实我认为,你的问题的线索如下:
您首先为会计模块添加路由,当然在该模块中您将它们标记为 forChild。
然后,您添加了主 AppModuleRouts。
在您的应用程序被编译并且 运行 - etire RouterTree 包括所有可能的路径之后。因此,来自 AccountModule 的路由实际上成为了子路由。
因此,就您在空路由上应用 canActivate: [AuthGuard] 而言——最一般的可能是——它每次都会触发。
这个问题实际上是由我定义初始状态的 ngrx-router
实现引起的。
最初的初始状态是按照此处建议的以下方式设置的 - https://github.com/ngrx/platform/issues/835#issuecomment-369592809
export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
state: {
url: window.location.pathname,
queryParams: getQueryParams(window.location.search.substring(1)),
params: {}
},
navigationId: 0
}
这不适用于生产版本。例如,直接导航到 /activate
之类的路线会导致路由器状态与 angular 路由器状态之间存在差异,从而取消导航。
top设置初始路由器状态的正确方法如下...
export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
state: {
url: '/',
queryParams: {},
params: {}
},
navigationId: 0
}
在 app-routing.module
中使用 initialNavigation: 'enabled'
,路由器状态会在尽可能早的时间点更新,并与 angular 路由器同步。
我遇到了 Angular 似乎没有多大意义的路由问题。通过以下设置,会出现此结果...
- 应用加载路径
/
- Auth guard 运行s
- Auth guard returns false 因为存储中还没有 JWT
- 重定向到
/login
按预期工作。
然而...
- 直接导航到
/activate
(帐户模块中的路由) - 控制台记录身份验证守卫 运行(这不应该发生)
- 重定向到
/login
我很难理解为什么 auth guard 运行宁 /activate
路由不是仪表板布局的子路由。
应用程序路由
{
path: '',
component: DashboardLayoutComponent,
canActivate: [AuthGuard],
canActivateChild: [DashboardGuard],
children: [
{
path: 'schedule',
loadChildren: () =>
import('@libs/schedule').then(
i => i.ScheduleModule
),
data: {
breadcrumb: 'Schedule'
}
},
// Other feature modules omitted
{
path: '',
redirectTo: '/schedule',
pathMatch: 'full'
}
]
}
账户路由
{ path: 'login', component: LoginComponent },
{ path: 'activate', component: ActivateComponent }
Auth Guard
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private jwtService: JwtService,
private router: Router,
private accountService: accountService
) { }
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
console.log('Auth Guard Start'); // <-- This appears in console
return this.jwtService.getToken().pipe(
map(token => {
if (!token) {
this.router.navigate(['/login']);
return false;
}
// Attempt to populate the user using the token.
this.accountService.populate();
return true;
}),
take(1)
);
}
}
应用模块
@NgModule({
declarations: [AppComponent, DashboardLayoutComponent],
imports: [
// .. other modules omitted
AccountModule,
AppRoutingModule
],
providers: [AuthGuard, DashboardGuard],
bootstrap: [AppComponent]
})
export class AppModule { }
附加信息
这仅在 运行 处于生产模式时发生。
Augury 报告说 /login
和 /activate
都是 /
路线的兄弟姐妹。 https://imgur.com/a/CJyKu8C
@angular/core: 8.2.6
@angular/router: 8.2.6
其实我认为,你的问题的线索如下:
您首先为会计模块添加路由,当然在该模块中您将它们标记为 forChild。 然后,您添加了主 AppModuleRouts。 在您的应用程序被编译并且 运行 - etire RouterTree 包括所有可能的路径之后。因此,来自 AccountModule 的路由实际上成为了子路由。 因此,就您在空路由上应用 canActivate: [AuthGuard] 而言——最一般的可能是——它每次都会触发。
这个问题实际上是由我定义初始状态的 ngrx-router
实现引起的。
最初的初始状态是按照此处建议的以下方式设置的 - https://github.com/ngrx/platform/issues/835#issuecomment-369592809
export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
state: {
url: window.location.pathname,
queryParams: getQueryParams(window.location.search.substring(1)),
params: {}
},
navigationId: 0
}
这不适用于生产版本。例如,直接导航到 /activate
之类的路线会导致路由器状态与 angular 路由器状态之间存在差异,从而取消导航。
top设置初始路由器状态的正确方法如下...
export const routerInitialState: fromRouter.RouterReducerState<RouterStateUrl> = {
state: {
url: '/',
queryParams: {},
params: {}
},
navigationId: 0
}
在 app-routing.module
中使用 initialNavigation: 'enabled'
,路由器状态会在尽可能早的时间点更新,并与 angular 路由器同步。