Angular - 无法获取当前用户在 guard 中的角色以检查 he/she 是否有权访问受保护的路由
Angular - Cannot get current user's role in guard to check if the he/she has permission to access protected routes
我正在尝试在基于 Angular
的项目上实施 基于角色的访问控制 ,其中有多种类型的角色
我想在CanActivate
接口中获取用户的数据(角色属性),以检查用户是否有权访问guard
中受保护的routes
,但是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)
})
}
Auth Guard
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) => {
.......
.......
}
然后有一个
属性 'canActivate' in type 'AuthGuard' is not assignable to the same 属性 in base type 'CanActivate' 错误,
因为 Subscription
类型不能分配给类型 boolean
.
因此,您能否给出任何提示或推荐使用可观察对象处理 angular
中的 RBAC 的更好方法。
P.S.
我看到 solutions 和 localStorage
,但我不想在那里保留用户数据(令牌除外)。
问题是 userRole$
observable emmits null
最初是因为它订阅了 userRole BehaviorSubject
,它获取 null 作为参数。
因此,userRole$ observable 等于 null 得到更新,属性 canActivate in type AuthGuard cannot return null.
因此,您应该在将对象传递给映射之前使用 filter() 运算符,以消除空值。
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 {
....
}
)
}
我正在尝试在基于 Angular
的项目上实施 基于角色的访问控制 ,其中有多种类型的角色
我想在CanActivate
接口中获取用户的数据(角色属性),以检查用户是否有权访问guard
中受保护的routes
,但是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)
})
}
Auth Guard
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) => {
.......
.......
}
然后有一个
属性 'canActivate' in type 'AuthGuard' is not assignable to the same 属性 in base type 'CanActivate' 错误,
因为 Subscription
类型不能分配给类型 boolean
.
因此,您能否给出任何提示或推荐使用可观察对象处理 angular
中的 RBAC 的更好方法。
P.S.
我看到 solutions 和 localStorage
,但我不想在那里保留用户数据(令牌除外)。
问题是 userRole$
observable emmits null
最初是因为它订阅了 userRole BehaviorSubject
,它获取 null 作为参数。
因此,userRole$ observable 等于 null 得到更新,属性 canActivate in type AuthGuard cannot return null.
因此,您应该在将对象传递给映射之前使用 filter() 运算符,以消除空值。
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 {
....
}
)
}