概念
RBAC(Role-Based Access Control )基于角色的访问控制。
RBAC认为权限的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。
3、RBAC96是一个模型族,其中包括RBAC0~RBAC3四个概念性模型。
1、)基本模型RBAC0定义了完全支持RBAC概念的任何系统的最低需求。
2、)RBAC1和RBAC2两者都包含RBAC0,但各自都增加了独立的特点,它们被称为高级模型。
RBAC1中增加了角色分级的概念,一个角色可以从另一个角色继承许可权。
RBAC2中增加了一些限制,强调在RBAC的不同组件中在配置方面的一些限制。
3、)RBAC3称为统一模型,它包含了RBAC1和RBAC2,利用传递性,也把RBAC0包括在内。
代码示例
/**
* 操作权限校验
* @param userId 用户id Who
@param documentId 知识库id、目录id、文档id what
* @param operationEnum 操作类型 How
*
*
*/
public void checkOperationAuthority(OperationEnum operationEnum, String userId, String documentId) {
switch (operationEnum) {
// 1. 知识库所有者或管理员有权限
case DC_LIBRARY_ADD:
// 新增知识库目录、文档
case DC_LIBRARY_RENAME:
// 重命名
case READ_NOTIFY_SETTING:
// 查看提醒
case DC_LIBRARY_DOCUMENT_SAVE:
// 保存文档
checkRoleOwnerOrAdmin(userId, documentId);
break;
// 2. 所有者有权限
case DC_LIBRARY_SETTING:
// 知识库设置
case MEMBER:
// 知识库人员设置
case SHARE_SETTING:
// 分享
checkRoleOwner(userId, documentId);
break;
// 3. 自定义权限判断
case DC_LIBRARY_DEL:
// 删除知识库(知识库、目录、文档)权限校验
delDcLibraryRole(userId, documentId);
break;
default:
throw new BusinessException("无权操作");
}
}
/**
* 权限校验——知识库“拥有者” 或 “管理员”有权操作
*
* @param userId 用户id
* @param documentId 知识库id(可以是知识库id、目录id、文档id。最终都会以知识库id查询权限)
*/
private void checkRoleOwnerOrAdmin(String userId, String documentId) {
DcLibraryUser dcLibraryUser = getUserRole(userId, documentId);
boolean flag = dcLibraryUser == null ||
(!DcLibraryUserRoleEnum.owner.equals(dcLibraryUser.getRole()) && !DcLibraryUserRoleEnum.admin.equals(dcLibraryUser.getRole()));
if (flag) {
throw new BusinessException("知识库所有者或管理员有权操作");
}
}
/**
* 查询用户知识库权限
*
* @param userId 用户id
* @param documentId 知识库id(可以是知识库id、目录id、文档id。最终都会以知识库id查询权限)
*/
private DcLibraryUser getUserRole(String userId, String documentId) {
if (StringUtils.isBlank(userId) && StringUtils.isBlank(documentId)) {
log.error("权限校验入参为空:userId:{}, documentId: {}", userId, documentId);
throw new BusinessException("无权操作");
}
// 查询知识库
DcLibrary dcLibrary = dcLibraryService.getKnowledgeByChildren(documentId);
if (dcLibrary == null) {
throw new BusinessException("知识库不存在");
}
// 拥有者才有权限
return dcLibraryUserService.getOne(Wrappers.<DcLibraryUser>lambdaQuery()
.eq(DcLibraryUser::getUserId, userId)
.eq(DcLibraryUser::getDcLibraryId, dcLibrary.getId())
.select(DcLibraryUser::getRole));
}
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("知识库-文档对应的用户")
@EqualsAndHashCode(callSuper = false)
@TableName("dc_library_user")
public class DcLibraryUser extends BasalPo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("用户名")
private String realName;
@ApiModelProperty("知识库的ID值")
private String dcLibraryId;
@ApiModelProperty(" 权限/所有者、管理员、成员")
private DcLibraryUserRoleEnum role;
@ApiModelProperty("是否删除 0未删除 1已删除")
@TableLogic
private Boolean delFlag;
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ApiModelProperty("租户")
@TableField("tenant_id")
private String tenantId;
}
@Getter
public enum DcLibraryUserRoleEnum {
/**
* 所有者、、
*/
owner("owner","owner"),
/**
* 管理员
**/
admin("admin","admin"),
/**
* 成员
**/
member("member","member"),
;
@EnumValue
public final String value;
public final String desc;
DcLibraryUserRoleEnum(String value, String desc) {
this.value = value;
this.desc = desc;
}
}
、RBAC 权限体系设计
1、用户-角色-权限
RBAC0模式,包含了2种:
- 用户和角色是多对一关系,即:一个用户只充当一种角色,一种角色可以有多个用户担当;
- 用户和角色是多对多关系,即:一个用户可同时充当好几种角色,一种角色可以有多个用户担当;
权限体系,尽量可能地使用多对多的权限体系。
2、用户-组织-角色-权限
在“用户-角色-权限”的基础上,我们增加了用户与组织的关联关系,组织决定了用户的数据可视权限。但要想真正达到这个效果,我们还需要做2件事:
- 组织层级划分。
- 数据可视权限规则制定。比如:上级组织职能看到下级组织员工负责的数据,而不能看到其他平级组织及其下级组织的员工数据等。
通过以上两点,系统就可以在用户登录时,自动判断给用户展示哪些数据。
3、用户-组织-岗位-角色-权限
第三种权限体系又是在第二种权限体系上进行优化的,增加了用户与岗位的关联关系,示意图如下:
增加岗位有以下几点好处:
- 识别用户的主要身份。
- 一个人可能身兼多职(多个角色),但是他的主要职能是固定的,系统用户的主要职能 可以通过岗位区分。