繁体   English   中英

Angular - 无法获取当前用户在警卫中的角色以检查他/她是否有权访问受保护的路线

[英]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)  
            })
        }

身份验证卫士

    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

因此,您能否给出任何提示或推荐更好的方法来处理RBAC与 observables 的angular

聚苯乙烯

我已经看到localStorage 解决方案,但我不想将用户的数据(令牌除外)保留在那里。

问题是userRole$ observable 最初发出null因为它订阅了 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 {
        ....
      }
    )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM