防护可以在服务实例化之前运行



这很可能是一个非常微不足道的问题,我只是从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']);
}
}

相关内容

最新更新