我最近因为Angular护卫队而陷入困境。加载页面时,CanActive仅运行一次,而在受保护的路径中不会在路径更改时运行。我认为这已经改变了,因为它曾经用于每次改变。从我在论坛中看到的内容,我应该使用CanActivateChild。问题是,我们的应用程序包含几个模块,它们有几个路径后代,当我在根模块中使用CanActivateChild时,在更改路径时会多次调用它。
我觉得为每个孩子分配一个守卫是愚蠢的,因为对于AppModule来说,那些延迟加载的儿童模块应该只是“黑盒子”'我想定义所有这些模块都应该加以保护。
export const routes: Routes = [
{
path: '404',
component: NotFoundComponent
},
{
path: '',
canActivate: [AuthGuard],
component: FullLayoutComponent,
data: {
title: 'Home'
},
children: [
{
path: 'administration',
loadChildren: './administration/administration.module#AdministrationModule'
},
{
path: 'settings',
loadChildren: './settings/settings.module#SettingsModule'
}
]
},
{
path: '',
loadChildren: './account/account.module#AccountModule'
},
{
path: '**',
redirectTo: '404'
}
];
这有什么解决方案吗?或者您认为这不是问题'关于安全性?
谢谢大家。
答案 0 :(得分:5)
面对同样的问题,我在问题上找到的所有问题都是Github关于Angular devs声明的一些封闭问题,这种行为"是设计的"。
所以我最终做的是订阅app.component中的导航事件并在那里激活AuthGuard检查:
constructor(
private router: Router,
private route: ActivatedRoute,
private authGuard: AuthGuard,
) {}
ngOnInit() {
this.router.events
.subscribe(event => {
if (event instanceof RoutesRecognized) {
this.guardRoute(event);
}
}));
}
private guardRoute(event: RoutesRecognized): void {
if (this.isPublic(event)) {
return;
}
if (!this.callCanActivate(event, this.authGuard)) {
return;
}
}
private callCanActivate(event: RoutesRecognized, guard: CanActivate) {
return guard.canActivate(this.route.snapshot, event.state);
}
private isPublic(event: RoutesRecognized) {
return event.state.root.firstChild.data.isPublic;
}
AuthGuard非常标准:
@Injectable()
export class AuthGuard implements CanActivate{
constructor(private auth: AuthService, private router: Router) { }
canActivate(): Promise<boolean> {
return this.auth.isLoggedInPromise()
.then(isLoggedIn => {
if (!isLoggedIn) {
this.router.navigate(["/login"]);
}
return isLoggedIn;
});
}
}
公共路线应该像这样配置:
{
path: "login",
component: LoginComponent,
data: { isPublic: true }
}
此类实现的优点是默认情况下保护所有内容,并且应明确配置公共路由,这将减少使某些路由不受保护的可能性。还会将此重构为某种服务,以便能够在多个应用程序中使用它。
受this answer的启发。
答案 1 :(得分:1)
订阅路由器事件的问题是,导航已经开始并且历史记录已更新,这使得很难像护卫队一样以可靠的方式阻止导航。
但是Angular学会了为您提供一种配置守卫和分解器应如何在您的routes.ts
中直接行为的方式:
export const routes: Routes = [
{
path: '404',
component: NotFoundComponent
},
{
path: '',
canActivate: [AuthGuard],
runGuardsAndResolvers: 'always',
children: [
....
]
}
]
以下是文档:https://angular.io/api/router/RunGuardsAndResolvers
有一个不错的博客文章,解释了您的选择:https://juristr.com/blog/2019/01/Explore-Angular-Routers-runGuardsAndResolvers/