angular - Angular - 无法获取当前用户在警卫中的角色以检查他/她是否有权访问受保护的路线
问题描述
我正在尝试在有多种角色的基于项目的基础上实施基于角色的访问控制Angular
我想在CanActivate
界面中获取用户的数据(角色属性)以检查用户是否有权访问受保护routes
的 in guard
,但BehaviouralSubject
在接收到来自的最新值后不更新初始状态API
。
因此,我在身份验证服务中获取用户的数据,然后将接收到的值传递给userRole
主题,但更新的属性 (BehaviouralSubject) 在保护文件中不可用。
认证服务
constructor() {
let localToken: string
if (localStorage.getItem('token')) {
localToken = localStorage.getItem('token')
this.getUserInfo(localToken)
}
}
userRole = new BehaviorSubject(null)
userRole$ = this.userRole.asObservable()
// called in constructor of a auth. service (every time when user called)
// and after login as well, so user's data always available.
getUserInfo(data) {
this.requestService
.post('GET_USER_INFO', data)
.subscribe((response: ILoggedInUser) => {
// data from API {email: "test@test.com", userName: "ccc", role: "viewer"}
this.userRole.next(response.user)
})
}
认证卫士
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.userRole$.pipe(
map(member => {
if (member) {
// check if route is restricted by role
if (
route.data.roles &&
route.data.roles.indexOf(member.role) === -1
) {
// role not authorised so redirect to home page
this.router.navigate(['/login'])
return false
}
return true
} else {
this.router.navigate(['/login'])
return false
}
}),
)
}
这是路由:
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
},
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
data: { roles: ['admin'] },
},
{
path: 'editor',
component: EditorsComponent,
canActivate: [AuthGuard],
data: { roles: ['admin', 'editor'}
},
{
path: 'viewer',
component: ViewersComponent,
canActivate: [AuthGuard],
data: { roles: ['admin', 'viewer'] },
}
]
我也尝试了另一种方法,(例如使用订阅)但是当我尝试这样subscribe
的userRole
主题时:
return this.authService.userRole.subscribe((member) => {
.......
.......
}
那么
“AuthGuard”类型中的属性“canActivate”不可分配给基类型“CanActivate”错误中的同一属性,因为Subscription
类型不可分配给类型boolean
。
因此,您能否给出任何提示或推荐使用 observables处理RBAC的更好方法。angular
附言
我已经看到了解决方案,localStorage
但我不想将用户的数据(令牌除外)保留在那里。
解决方案
问题是userRole$
observablenull
最初会发出,因为它订阅了 userRole BehaviorSubject
,它作为参数获取 null 。
因此,userRole$ observable 等于 null 获取更新,并且类型 AuthGuard 中的属性 canActivate 不能返回 null。
因此,您应该在将对象传递给映射之前使用 filter() 运算符以消除 null。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.userRole$.pipe(
filter(member => !!member), // Filter NULL value here before sending object further
map(member => {
....
return true
} else {
....
}
)
}
推荐阅读
- elasticsearch - ElasticSearch:结果窗口太大
- html - 使用 SVG 作为具有 position: absolute 的灵活背景;
- node.js - 使用带有 findOne() 方法的 NodeJS 从 MongoDB 数据库获取服务器端变量信息的问题
- c - 如何根据桶大小更改除法哈希函数
- javascript - 如何等待数组完成,然后执行函数?
- java - 如何使用 SpringBoot 2 运行单元测试
- c# - 为什么我不能在 Session 中保存对象
- python - 在 Flask 中使用 WTForms 验证 GET 参数
- r - R中用于继承自定义数据框类的列的函数
- c# - 在 C# 中使用多线程的高 CPU