我正在尝试为我的应用程序提供基于角色的访问权限,我需要一些帮助,因为我是Angular的新手...
首先,这是我在确定哪些角色可以访问它的路线中所拥有的...
来自app-routing.module.ts
{
path: 'profile',
component: ComunityComponent,
canActivate: [AuthGuard],
data: {
allowedRoles: ['admin', 'user']
}
},
第二,我使用canActivate函数来检查用户是否可以访问路由。 来自auth.guard.ts
private hasAccess: boolean;
constructor(private router: Router, private auth: AuthService) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const allowedRoles = next.data.allowedRoles;
if (localStorage.getItem('currentUser')) {
return this.checkAccess(localStorage.getItem('currentUser'), allowedRoles);
}
this.router.navigate(['/login'], {queryParams: {returnUrl: state.url}});
return false;
}
第三,我开发了函数accessLoginToken,它将通过httpclient.get服务找到登录用户的角色,该服务返回一个数组,该数组具有分配给该用户的角色。示例{success: true, roles:['user']}
来自auth.service.ts
accessLoginToken(token: string) {
const check = '/users/access';
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'Bearer ' + token,
})
};
return this.http.get<any>('/api' + check, httpOptions).pipe(
catchError(err => this.handleError('accessLoginToken', err))
);
}
function checkAccess
中的第四项,我将其与路由的第四项进行了比较,如果它们匹配,则不允许访问。
来自auth.guard.ts
private checkAccess(token: string, allowedRoles: string[]): boolean {
this.hasAccess = false;
this.auth.accessLoginToken(token).subscribe(data => {
if (data.success) {
data.roles.forEach(rol => {
if (allowedRoles.findIndex(rols => rols === rol) >= 0) {
this.hasAccess = true;
}
});
}
}, (error) => {
console.log(error);
});
console.log(this.hasAccess);
return this.hasAccess;
}
主要问题是我无法让httpclient订阅将hasAccess变量的值更改为true以允许访问。即使执行了代码this.hasAccess = true;
,该函数也会返回假
顺便说一句,我不喜欢将角色保存在像access_token这样的会话变量中的想法,所以我试图将其保留在数据库中...
在这个问题上的任何帮助都将不胜感激..谢谢
答案 0 :(得分:2)
您是正确的,checkAccess
函数在异步api调用完成之前完成,因此总是返回false
。相反,您应该将可观察对象传递给canActivate方法。
private checkAccess(token: string, allowedRoles: string[]): boolean {
this.hasAccess = false;
return this.auth.accessLoginToken(token).pipe(
map(data => {
if (data.success) {
data.roles.forEach(rol => {
if (allowedRoles.findIndex(rols => rols === rol) >= 0) {
this.hasAccess = true;
}
});
}
return this.hasAccess;
})
)
}
因为可观察对象返回到canActivate
方法,所以警卫人员将订阅该可观察对象并等待结果为真或假。
答案 1 :(得分:0)
您的问题在于,当accessLoginToken仍在运行时,您返回this.hasAccess。您可以将可观察到的角保护罩返回。