我在路由的canActivate守卫中需要做两件事情。首先,我需要通过调用OpenIdcSecutiry服务来检查用户是否被授权。如果用户已经被授权,那么我还必须通过调用另一个返回包含用户角色的UserProfile的服务来检查用户的角色。我知道我可以返回一个Observable,实际上,如果我只这样做:
return this.oidcSecurityService.getIsAuthorized();
它可以工作,但显然我没有检查用户角色。现在我的代码是这样的:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.oidcSecurityService.getIsAuthorized()
.map(
data => {
if (data === false) {
this.router.navigate(['/login']);
return data;
}
if (data === true) {
const roles = route.data['roles'] as Array<string>;
if (roles) {
this.profileService.getObservableUserProfileFromServer().map(userProfile => {
const userRoles = userProfile.Roles;
for (const role of roles) {
if (userRoles.indexOf(role) > -1) {
return true;
}
}
return false;
});
}
return data;
}
},
error => {
this.router.navigate(['/login']);
return error;
}
);
this.profileService.getObservableUserProfileFromServer()从未被调用,我不知道如何在确认用户已经获得授权后检查用户角色。我该怎么做呢?我能在我的可观察对象中返回另一个可观察对象吗?
编辑1:我将代码更改为以下内容:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.oidcSecurityService.getIsAuthorized()
.map(
data => {
if (data === false) {
this.router.navigate(['/login']);
return data;
}
if (data === true) {
const roles = route.data['roles'] as Array<string>;
if (roles) {
return this.profileService.getObservableUserProfileFromServer().toPromise().then(userProfile => {
const userRoles = userProfile.Roles;
for (const role of roles) {
if (userRoles.indexOf(role) > -1) {
return true;
}
}
return false;
}
);
}
return data;
}
},
error => {
this.router.navigate(['/login']);
return error;
}
);
// 返回此.oidcSecurityService.getIsAuthorized();
}
现在我可以看到如何调用this.profileService.getObservableUserProfileFromServer并从服务器接收结果,但是结果没有在canActivate守卫中进行评估,它只是忽略了结果,并且显示导航已被取消。
最终编辑:
@llai 给了我答案,必须使用两个switchmap来链接多个observables,最终代码如下:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.oidcSecurityService.getIsAuthorized()
.switchMap(
data => {
if (data === false) {
this.router.navigate(['/login']);
return Observable.of(false); // user not logged in, canActivate = false
} else if (data === true) {
const roles = route.data['roles'] as Array<string>;
if (roles) {
// return inner observable
return this.profileService.getObservableUserProfileFromServer()
.switchMap(userProfile => {
const userRoles = userProfile.Roles;
for (const role of roles) {
if (userRoles.indexOf(role) > -1) {
// role found, canActivate = true
return Observable.of(true);
}
}
// no matching role, canActivate = false
return Observable.of(false);
});
} else {
// no roles defined in route data, canActivate = false
return Observable.of(true);
}
}
});
}