这很可能是一个非常微不足道的问题,我只是从AngularJS背景中挑选了Angular 2+。
最简单的是,我正在我的 angular 9 应用程序中实施身份验证,并偶然发现了我的警卫问题。
在我的authentication.service.ts
服务中,我正在使用用户类型的行为主体,并且我使用以下公共库将我的 User 对象保存在localStorage
中:https://github.com/cyrilletuzi/angular-async-local-storage
在我的authentication.service
构造函数中,我正在做这样的事情:
constructor(private request: RequestService, private storage: StorageMap) {
this.storage.get('currentUser').subscribe((user: User) => {
this.currentUserSubject = new BehaviorSubject<User>(user);
this.currentUser = this.currentUserSubject.asObservable();
});
}
和我的isAuthenticated
方法:
isAuthenticated() {
return this.currentUserSubject.value;
}
但是,这很好用,因为 storageMap 是一个可观察的,它需要一点时间才能返回,因此当我尝试检查用户是否在我的保护中进行身份验证时:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
不幸的是,this.currentUserSubject
是不确定的。因此,守卫在构造函数authentication.service
有机会正确实例化之前运行。
任何积分都将不胜感激。
更新:
我想我越来越近了(ish(。
在我的身份验证中,我的 isAuthenticated 方法现在看起来像这样(如下所述(
isAuthenticated() {
return this.currentUser
.pipe(filter(user => user));
}
尽管存在错误:论证类型用户不可分配给参数类型。
另外,如果我在 canActivate 中更改我的返回语句:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.isAuthenticated();
}
但我在控制台中得到这个
类型"可观察"不可分配给类型"可观察"。 类型"未知"不可分配给类型"布尔值 |网址树'。 类型"{}"缺少类型"UrlTree"中的以下属性:root,queryParams,fragment,queryParamMap
18 return this.authService.isAuthenticated();
async isAuthenticated() {
var res = await this.storage.get('currentUser').toPromise();
return res;
}
您面临的行为原因是,订阅是一个异步作业。 因此,类初始化在调用订阅后立即完成。订阅的回调将在稍后具有该数据时调用。在回拨之前,您被召唤了。
canActivate
方法必须返回Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
。
据我所知,您正在返回一个对象(用户(。
但是,在您的保护中,您应该使用可观察量而不是主题。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.authService.currentUser.pipe(map(user => !!user));
}
来自map
运算符的双重否定(!!
(将使可观测返回一个布尔值。
防护在导航时被激活,因此在导航到您的帖子登录页面之前,请确保您已设置用户。
constructor(private authenticationService: AuthenticationService, private router: Router) {}
ngOnInit() {
this.handleUserChange();
}
private handleUserChange(): void {
this.authenticationService.currentUserSubject
.pipe(filter(user => user)) // falsy value check
.subscribe(user =>
{
// Navigate to post login
this.router.navigate(['home-page']);
}
}