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名称,管理后台显示用
}
业务流程
服务端权限校验流程
- 当前请求接口有@RequirePermission注解,进入鉴权流程。没有@RequirePermission注解,返回鉴权成功
- 【当前请求接口的@RequirePermission内的权限列表】与【用户的拥有的权限列表】有交集,返回鉴权成功。无交集返回鉴权失败。
- RBAC服务器故障,导致角色数据无法获取时,返回鉴权失败,同时启动RBAC Server存活检测线程,存活检查按递增间隔进行检测。发现RBAC Server正常后,重新加载角色数据。
客户端权限校验流程
- 每个组件将自己的所有UI元素中涉及权限控制的资源做成【权限资源列表】,这些资源默认不可见。
- 从RBAC获取当前登录用户的可见资源列表。
- 当用户进入某个page时,获取【用户可见资源列表】与【权限资源列表】的交集,将交集的资源设置为可见。
- 如果RBAC服务端无法连接,则【用户可见资源列表】为空,这些受控资源不可见。
缓存更新流程
- 服务端的角色缓存数据通过MQ订阅通知实现实时更新。
- 客户端如果使用IM组件时,通过IM事件消息触发更新。如果未使用IM组件,采用定时到服务端检查版本变更的策略,如果数据有更新再去RBAC服务端拉取。