RBAC实践

RBAC,即大家很熟悉的“基于角色的访问控制”。理论什么的这里就不讲了,重点介绍下一种基于RBAC的实践。

名词解释

  • 领域:Realm,角色的定义范围。
  • 角色:Role,一组权限的集合。角色必须定义在指定领域内
  • 资源:Resource,主要应用于前端UI元素可见性方面的权限管控
  • 操作:Action,主要应用于服务端api调用合法性方面的管控
  • 权限:Permission,一组“资源+操作”的组合,并具备一个用户易于理解的名称

数据结构

角色 ROLE_INFO

{
    "id":"", // 角色id
    "tenant":"", // 租户id
    "code":"", // 角色代码
    "realm":"", // 角色领域,global:应用内全局角色;app:app端角色;admin:管理端角色;web: web前端角色;
    "realm_id":"", // 领域id,选填。
    "name":"", // 角色名称
    "status":0, // 状态,0 启用,1 禁用
    "type":0, // 类型:0 正常角色,1 临时角色,2 默认角色
    "valid":1, // 2:未生效,1:生效
    "valid_time":"", // 生效时间
    "invalid_time":"", // 失效时间
    "remark":"管理员", // 角色备注
    "permissions": // 分配的权限列表
        [
            PERMISSION_INFO
        ]
}

资源 RESOURCE_INFO

{
    "id":"", // 资源id
    "client":"", // 客户端类型,取值:app,web,admin
    "code":"", // 资源标识符,客户端控制用,全局唯一
    "tag":"", // 资源标签
    "remark":"" // 资源名称,管理后台显示用
}

权限 PERMISSION_INFO

{
    "id":"", // 权限id
    "name":"", // 权限名称
    "code":"", // 权限代码
    "status":0, // 状态,0 启用,1 禁用
    "remark":"", // 权限备注
    "actions":[ // 权限对应的ACTION列表
        ACTION_INFO,
        ACTION_INFO,
        ...
    ],
    "resources":[ // 权限对应的资源列表
        RESOURCE_INFO,
        RESOURCE_INFO,
        ...
    ]
}

操作 ACTION_INFO

{
    "id":"", // 操作id
    "code":"", // 全局唯一:包名.类名.方法
    "biz_type":"", // 二级服务需要填写此项
    "uri":"", // Restful api,管理后台显示用
    "remark":"" // api名称,管理后台显示用
}

业务流程

服务端权限校验流程

  1. 当前请求接口有@RequirePermission注解,进入鉴权流程。没有@RequirePermission注解,返回鉴权成功
  2. 【当前请求接口的@RequirePermission内的权限列表】与【用户的拥有的权限列表】有交集,返回鉴权成功。无交集返回鉴权失败。
  3. RBAC服务器故障,导致角色数据无法获取时,返回鉴权失败,同时启动RBAC Server存活检测线程,存活检查按递增间隔进行检测。发现RBAC Server正常后,重新加载角色数据。

客户端权限校验流程

  1. 每个组件将自己的所有UI元素中涉及权限控制的资源做成【权限资源列表】,这些资源默认不可见。
  2. 从RBAC获取当前登录用户的可见资源列表。
  3. 当用户进入某个page时,获取【用户可见资源列表】与【权限资源列表】的交集,将交集的资源设置为可见。
  4. 如果RBAC服务端无法连接,则【用户可见资源列表】为空,这些受控资源不可见。

缓存更新流程

  1. 服务端的角色缓存数据通过MQ订阅通知实现实时更新。
  2. 客户端如果使用IM组件时,通过IM事件消息触发更新。如果未使用IM组件,采用定时到服务端检查版本变更的策略,如果数据有更新再去RBAC服务端拉取。