编辑如下
我不想在每次更改路线时都打电话来确定用户是否已通过身份验证,但是我想检查一下,如果他们刷新了经过身份验证的路由上的页面,他们是否可以访问它。我似乎无法完成这项工作。
我有一项服务,可以简单地检查与api的会话,如下所示:
authenticate(): Observable<boolean> {
return this.http.post<boolean>(this._authUrl, {}, {})
}
端点从字面上返回true
或false
。我在app.component
上运行它,因此这是第一件事,它不再需要再次请求。
ngOnInit() {
this.userService.authenticate().subscribe((response) => {
this.userService.loggedIn = response;
})
}
然后我定义了一条这样的路线:
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuardService],
pathMatch: 'full'
},
然后在我的authguard
服务中,我有这个:
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): any{
return this.userService.loggedIn
})
}
如果您登陆/
并导航至/dashboard
,此方法就很好了。但是,如果您登录并刷新/dashboard
上的页面,该组件将永远不会加载。它会加载导航等内容,但不会加载仪表板组件或模板。 /authenticate
确实可以运行,但是在端点响应之前,路由保护程序似乎已经查看loggedIn
。
我尝试使用loggedIn
将of
变量放入一个可观察的对象,这似乎没有什么区别,最终结果是相同的。
我查找的所有内容似乎都是用于通过URL检查身份验证并以这种方式使用可观察对象,但是当它已经知道用户从第一个初始名称进行身份验证时,我真的不想发出http请求请求。
编辑:
我认为,考虑此问题的更好方法是,我希望/authenticate
响应在加载其他任何内容之前已经准备好。使用Route Guard,我必须将登录页面锁定在登录之后,而我不想这样做。但是我也希望根/authenticate
可以访问app.component
的响应,因为那是我的导航所在,也是用户登录的指示器。
因此,对我来说似乎有意义的是,如果我可以告诉angular在完成所有操作之前先在/authenticate
上等待,即使他们刷新了{{1}上的页面},/dashboard
响应已经在那里,因此我不必担心这种令人讨厌的比赛条件。我可以这样做吗?
答案 0 :(得分:-1)
我会做这样的事情:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
if (this.getUser) this.getUser.unsubscribe();
this.getUser = this.authService.getUser().subscribe(r => {
resolve(true);
}, (err) => {
reject(err);
});
});
}
这:
getUser(): Observable<UserDTO> {
if (this.user) return new Observable(o => o.next(this.user));
return this.http.get<UserDTO>(URL, { withCredentials: true })
.pipe(
map(u => new UserDTO(u)),
tap(u => {
this.user = u;
this.isLogined = true;
})
);
}
并从组件中删除逻辑。这一定要警惕。