基于RBAC模型的权限管理实现详解
简介
在现代企业级应用中,权限管理是确保系统安全性和数据完整性的核心模块之一。通过权限管理,系统可以为不同的用户分配不同的权限,从而实现对系统资源的精细控制。本文将详细介绍一个基于Spring Boot和RBAC(Role-Based Access Control,基于角色的访问控制)模型的权限管理模块的实现过程,涵盖用户、角色、权限的管理以及它们之间的关系。
RBAC模型简介
RBAC(Role-Based Access Control)是一种常见的权限管理模型,它将权限分配给角色,然后将角色分配给用户。通过这种方式,系统可以灵活地管理用户权限,而不需要为每个用户单独分配权限。RBAC模型的核心概念包括:
- 用户(User): 系统的使用者,可以是管理员、普通用户等。
- 角色(Role): 一组权限的集合,用户通过角色来获得权限。
- 权限(Permission/Entitlement): 系统中对资源的操作权限,如查看、编辑、删除等。
- 用户-角色关系(User-Role Relationship): 用户与角色之间的关联关系。
- 角色-权限关系(Role-Permission Relationship): 角色与权限之间的关联关系。
项目结构
项目的主要代码结构如下:
- UserController.java: 用户管理的控制器,负责处理用户相关的HTTP请求。
- RoleController.java: 角色管理的控制器,负责处理角色相关的HTTP请求。
- EntitlementController.java: 权限管理的控制器,负责处理权限相关的HTTP请求。
- UserService.java, RoleService.java, EntitlementService.java: 服务接口,定义了用户、角色、权限管理的核心业务逻辑。
- UserServiceImpl.java, RoleServiceImpl.java, EntitlementServiceImpl.java: 服务实现类,具体实现了用户、角色、权限管理的业务逻辑。
- SysUser.java, SysRole.java, SysEntitlement.java: 实体类,分别对应数据库中的用户表、角色表和权限表。
- SysUserRoleRela.java, SysRoleEntRela.java: 关联表实体类,分别对应数据库中的用户-角色关联表和角色-权限关联表。
- SysUserMapper.xml, SysRoleMapper.xml, SysEntitlementMapper.xml: MyBatis的Mapper文件,定义了用户、角色、权限相关的SQL操作。
功能实现解析
1. 用户管理
用户管理模块负责管理系统的用户信息,包括用户的增删改查、用户状态的修改等。用户通过角色来获得权限,因此用户管理模块与角色管理模块紧密相关。
1.1 用户查询
具体实现:
-
参数校验:检查分页参数是否为空,如果为空则设置默认值。
if (ObjectUtil.isEmpty(stratPage)){ stratPage = 1; } if (ObjectUtil.isEmpty(limit)){ limit = 10; }
-
查询用户列表:调用
userMapper.selectUserByUserIdOrUserName
方法,根据用户ID或用户名进行模糊查询,并返回分页结果。List<SysUser> records = userMapper.selectUserByUserIdOrUserName(userId, userName, stratPage, limit);
-
返回结果:将查询结果封装到
UserListDTO
对象中返回。UserListDTO userListDTO = new UserListDTO(); userListDTO.setCurrent(current); userListDTO.setTotal(total); userListDTO.setRecords(records); userListDTO.setHasNext(hasNext); return ResSerialization.success(userListDTO);
1.2 用户创建
具体实现:
-
参数校验:检查用户名、真实姓名、手机号等是否为空,如果为空则抛出相应的异常。
if (ObjectUtil.isEmpty(userInsertVO.getUserName())){ throw new QLException(USER_NAME_NOT_NULL); } if (ObjectUtil.isEmpty(userInsertVO.getRealname())){ throw new QLException(REALNAME_NOT_NULL); } if (ObjectUtil.isEmpty(userInsertVO.getTelphone())){ throw new QLException(TELPHONE_NOT_NULL); }
-
保存用户信息:将
UserInsertVO
中的属性复制到SysUser
对象中,并保存到用户表中。SysUser sysUser = BeanUtil.copyProperties(userInsertVO, SysUser.class); sysUser.setCreatedAt(new Date()); sysUser.setUpdatedAt(new Date()); OperationUtil.executeOperation(() -> this.save(sysUser), USER_SAVE_ERROR);
-
返回结果:返回创建操作的结果。
return ResSerialization.success();
2. 角色管理
角色管理模块负责管理系统的角色信息,包括角色的增删改查、角色与权限的关联等。角色是权限的集合,用户通过角色来获得权限。
2.1 角色查询
具体实现:
-
参数校验:检查分页参数是否为空,如果为空则设置默认值。
if (ObjectUtil.isEmpty(stratPage)){ stratPage = 1; } if (ObjectUtil.isEmpty(limit)){ limit = 10; }
-
查询角色列表:调用
roleMapper.selectRoleList
方法,根据角色ID或角色名称进行模糊查询,并返回分页结果。List<SysRole> records = roleMapper.selectRoleList(roleId, roleName, stratPage, limit);
-
返回结果:将查询结果封装到
RoleListDTO
对象中返回。RoleListDTO roleListDTO = new RoleListDTO(); roleListDTO.setCurrent(current); roleListDTO.setTotal(total); roleListDTO.setRecords(records); roleListDTO.setHasNext(hasNext); return ResSerialization.success(roleListDTO);
2.2 角色创建
具体实现:
-
参数校验:检查角色名称和权限ID列表是否为空,如果为空则抛出相应的异常。
if (ObjectUtil.isEmpty(roleCreateVO.getRoleName())){ throw new QLException(ROLE_NAME_NOT_NULL); } if (ObjectUtil.isEmpty(roleCreateVO.getEntIdListStr())){ throw new QLException(ENT_ID_LIST_NOT_NULL); }
-
保存角色信息:将
RoleCreateVO
中的属性复制到SysRole
对象中,并保存到角色表中。SysRole sysRole = BeanUtil.copyProperties(roleCreateVO, SysRole.class); sysRole.setRoleId(ROLE_ID + IdUtil.fastSimpleUUID()); sysRole.setCreatedAt(new Date()); sysRole.setUpdatedAt(new Date()); OperationUtil.executeOperation(() -> this.save(sysRole), ROLE_SAVE_ERROR);
-
保存角色与权限的关联信息:将角色ID和权限ID列表保存到角色与权限的关联表中。
List<String> entIdList = Arrays.asList(roleCreateVO.getEntIdListStr().split(",")); for (String entId : entIdList) { SysRoleEntRela sysRoleEntRela = new SysRoleEntRela(); sysRoleEntRela.setRoleId(sysRole.getRoleId()); sysRoleEntRela.setEntId(entId); OperationUtil.executeOperation(() -> sysRoleEntRelaMapper.insert(sysRoleEntRela), ROLE_ENT_RELA_SAVE_ERROR); }
-
返回结果:返回创建操作的结果。
return ResSerialization.success();
3. 权限管理
权限管理模块负责管理系统的权限信息,包括权限的增删改查、权限与角色的关联等。权限是系统中对资源的操作权限,如查看、编辑、删除等。
3.1 权限查询
具体实现:
-
参数校验:检查分页参数是否为空,如果为空则设置默认值。
if (ObjectUtil.isEmpty(stratPage)){ stratPage = 1; } if (ObjectUtil.isEmpty(limit)){ limit = 10; }
-
查询权限列表:调用
entitlementMapper.selectEntitlementList
方法,根据权限ID或权限名称进行模糊查询,并返回分页结果。List<SysEntitlement> records = entitlementMapper.selectEntitlementList(entId, entName, stratPage, limit);
-
返回结果:将查询结果封装到
EntitlementListDTO
对象中返回。EntitlementListDTO entitlementListDTO = new EntitlementListDTO(); entitlementListDTO.setCurrent(current); entitlementListDTO.setTotal(total); entitlementListDTO.setRecords(records); entitlementListDTO.setHasNext(hasNext); return ResSerialization.success(entitlementListDTO);
3.2 权限创建
具体实现:
-
参数校验:检查权限名称、菜单图标、菜单URI、组件名称等是否为空,如果为空则抛出相应的异常。
if (ObjectUtil.isEmpty(entitlementCreateVO.getEntName())){ throw new QLException(ENT_NAME_NOT_NULL); } if (ObjectUtil.isEmpty(entitlementCreateVO.getMenuIcon())){ throw new QLException(MENU_ICON_NOT_NULL); } if (ObjectUtil.isEmpty(entitlementCreateVO.getMenuUri())){ throw new QLException(MENU_URI_NOT_NULL); } if (ObjectUtil.isEmpty(entitlementCreateVO.getComponentName())){ throw new QLException(COMPONENT_NAME_NOT_NULL); }
-
保存权限信息:将
EntitlementCreateVO
中的属性复制到SysEntitlement
对象中,并保存到权限表中。SysEntitlement sysEntitlement = BeanUtil.copyProperties(entitlementCreateVO, SysEntitlement.class); sysEntitlement.setEntId("ENT_" + IdUtil.fastSimpleUUID()); sysEntitlement.setCreatedAt(new Date()); sysEntitlement.setUpdatedAt(new Date()); OperationUtil.executeOperation(() -> this.save(sysEntitlement), ENTITLEMENT_SAVE_ERROR);
-
返回结果:返回创建操作的结果。
return ResSerialization.success();
4. 权限控制
在EntitlementController
中,使用了SaCheckRole
注解进行权限控制。例如,创建权限和更新权限的操作需要特定的角色权限才能执行。通过StpUtil.getLoginIdAsLong()
方法获取当前登录用户的ID,并进行权限校验。
@SaCheckRole(value = {"admin", "super_admin"}, mode = SaMode.OR)
@PostMapping()
ResSerialization<String> createEntitlement(@RequestBody EntitlementCreateVO entitlementCreateVO){
// 创建权限逻辑
}
@SaCheckRole(value = {"admin", "super_admin"}, mode = SaMode.OR)
@PutMapping("/{entId}")
ResSerialization<String> updateEntitlement(@PathVariable String entId, @RequestBody EntitlementUpdateVO entitlementUpdateVO){
// 更新权限逻辑
}