0


谷粒学院权限管理模块

文章目录

谷粒学院项目权限管理模块

1.数据库表

这里系统权限控制采用的访问控制模型是 RBAC 模型

RBAC模型

RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。

简单地说:一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,这样就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图:

RBAC

在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。

  • 菜单表acl_permissionimage-20211224190642029
  • 角色表acl_roleimage-20211224190701116
  • 用户表acl_userimage-20211224190713944
  • 角色—菜单表acl_role_permissionimage-20211224190732158
  • 用户—角色表acl_user_roleimage-20211224190744172

几个表之间的关系:

image-20211218161418810

2.菜单相关操作

2.1 递归查询全部菜单

controller

/**
 * 递归获取全部菜单 √
 * @return R
 */@GetMappingpublicRindexAllPermission(){List<Permission> list =  permissionService.queryAllMenuGuli();returnR.ok().data("children",list);}
service

/**
 * 递归查询所有菜单
 *
 * @return
 */@OverridepublicList<Permission>queryAllMenuGuli(){//1.查询菜单表所有数据LambdaQueryWrapper<Permission> queryWrapper =newLambdaQueryWrapper<>();//按id从大到小排序
    queryWrapper.orderByDesc(Permission::getId);List<Permission> permissionList = baseMapper.selectList(queryWrapper);//2.把查询所有的菜单按照要求封装List<Permission> resultList =bulidPermission(permissionList);return resultList;}

把返回所有菜单list集合进行封装,具体分为这几步:

  1. 创建list集合,用于数据最终封装
  2. 把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level=1
  3. 根据顶层菜单,向里面进行查询子菜单,封装到最终返回结果finalNode里面
/**
 * 把返回所有菜单list集合进行封装的方法
 *
 * @param permissionList
 * @return
 */publicstaticList<Permission>bulidPermission(List<Permission> permissionList){//1.创建list集合,用于数据最终封装List<Permission> finalNode =newArrayList<>();//2.把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1for(Permission permission : permissionList){//得到顶层菜单 pid=0菜单if("0".equals(permission.getPid())){//设置顶层菜单的level是1
            permission.setLevel(1);//3.根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
            finalNode.add(selectChildren(permission, permissionList));}}return finalNode;}

递归查找当前菜单的所有子菜单,具体分这几步:

  1. 因为向一层菜单里面放二层菜单,二层里面还要放三层,所以先把把子菜单集合初始化
  2. 遍历所有菜单list集合,进行判断比较,比较当前菜单pid和传过来的父菜单id值是否相同,相同就是该父菜单的子菜单
  3. 设置当前菜单level为父菜单level+1
  4. 设置子菜单,子菜单依然需要递归查询子菜单是否也有子菜单
/**
 * 递归查找当前菜单的所有子菜单
 *
 * @param permissionNode 需要查找子菜单的当前菜单
 * @param permissionList 所有菜单的集合
 * @return
 */privatestaticPermissionselectChildren(Permission permissionNode,List<Permission> permissionList){//因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
    permissionNode.setChildren(newArrayList<Permission>());//遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同,是不是当前菜单的子菜单for(Permission permission : permissionList){//当前菜单的pid=上级菜单idif(permission.getPid().equals(permissionNode.getId())){int level = permissionNode.getLevel()+1;//设置当前菜单level为父菜单level+1
            permission.setLevel(level);//设置子菜单,子菜单依然需要递归查询子菜单是否也有子菜单
            permissionNode.getChildren().add(selectChildren(permission, permissionList));}}return permissionNode;}

2.2 递归删除菜单

controller

/**
 * 递归删除菜单 √
 * @param id
 * @return
 */@DeleteMapping("remove/{id}")publicRremove(@PathVariableString id){
    permissionService.removeChildByIdGuli(id);returnR.ok();}
service

/**
 * 递归删除菜单
 *
 * @param id 菜单id
 */@OverridepublicvoidremoveChildByIdGuli(String id){//1.创建list集合,用于封装所有删除菜单id值List<String> idList =newArrayList<>();//2.加入所有子菜单的idthis.selectPermissionChildById(id, idList);//3.加入自己的id
    idList.add(id);//4.批量根据id删除菜单
    baseMapper.deleteBatchIds(idList);}

根据当前菜单id,查询其所有的子菜单的id并放入idList,分为这几步:

  1. 根据id查询下一层子菜单
  2. 循环变量子菜单list,将id放入idList
  3. 递归求子id的子id,也放入idList,以此类推
/**
 * 根据当前菜单id,查询菜单里面子菜单id,封装到list集合
 *
 * @param id 当前菜单id
 * @param idList 最终封装要删除的id集合
 */privatevoidselectPermissionChildById(String id,List<String> idList){LambdaQueryWrapper<Permission> queryWrapper =newLambdaQueryWrapper<>();//1.查询菜单里面子菜单id
    queryWrapper.eq(Permission::getPid, id);//2.只需要id
    queryWrapper.select(Permission::getId);List<Permission> childIdList = baseMapper.selectList(queryWrapper);//3.遍历子id集合,加入idList,然后递归遍历子菜单的子菜单
    childIdList.stream().forEach(item ->{
        idList.add(item.getId());selectPermissionChildById(item.getId(), idList);});}

2.3 给角色分配权限

controller

根据角色id和菜单id集合,一个角色分配多个菜单(权限):

/**
 * 给角色分配权限 √
 * @param roleId  角色id
 * @param permissionId 分配的菜单id集合
 * @return
 */@PostMapping("/doAssign")publicRdoAssign(String roleId,String[] permissionId){
    permissionService.saveRolePermissionRealtionShipGuli(roleId,permissionId);returnR.ok();}
service

/**
 * 角色分配菜单
 *
 * @param roleId        角色id
 * @param permissionIds 菜单id集合
 */@OverridepublicvoidsaveRolePermissionRealtionShipGuli(String roleId,String[] permissionIds){//1.创建list集合,用于封装添加数据List<RolePermission> permissionList =newArrayList<>();for(String permissionId : permissionIds){if(StringUtils.isEmpty(permissionId))continue;RolePermission rolePermission =newRolePermission();
        rolePermission.setPermissionId(permissionId);
        rolePermission.setRoleId(roleId);
        permissionList.add(rolePermission);}//2.批量保存到acl_role_permission表
    rolePermissionService.saveBatch(permissionList);}

2.4 根据角色获取菜单

controller

根据角色id获取对应的拥有的菜单集合:

/**
 * 根据角色获取菜单
 * @param roleId
 * @return
 */@GetMapping("toAssign/{roleId}")publicRtoAssign(@PathVariableString roleId){List<Permission> list = permissionService.selectAllMenu(roleId);returnR.ok().data("children", list);}
service

根据角色id获取菜单集合,具体分为这几步:

  1. 查询所有Perssion,并按id排序得到permissionList
  2. 根据roleId查询在acl_role_permission表里查询所有RolePerssion得到rolePermissionList
  3. 用stream将rolePermissionList所有对应的permissionId提取出来得到permissionIdList
  4. 遍历permissionList,如果对象的id是目标集合permissionIdList里的id,则设置select为true
  5. 把所有的菜单list集合permissionList进行树状封装,递归封装,最终返回
/**
 * 根据角色获取菜单
 *
 * @param roleId 角色id
 * @return
 */@OverridepublicList<Permission>selectAllMenu(String roleId){//1.查询所有Perssion,并按id排序List<Permission> permissionList = baseMapper.selectList(newLambdaQueryWrapper<Permission>().orderByDesc(Permission::getId));//2.根据roleId查询在acl_role_permission表里查询所有RolePerssionList<RolePermission> rolePermissionList = rolePermissionService.list(newLambdaQueryWrapper<RolePermission>().eq(RolePermission::getRoleId, roleId));//3.用stream将rolePermissionList所有对应的permissionId提取出来List<String> permissionIdList = rolePermissionList.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());//4.遍历permissionList,如果对象的id是目标集合permissionIdList里的id,则设置select为true
    permissionList.forEach(permission->{if(permissionIdList.contains(permission.getId())){
            permission.setSelect(true);}else{
            permission.setSelect(false);}});//5.把所有的菜单list集合进行树状封装,递归封装List<Permission> resPermission =bulidPermission(permissionList);return resPermission;}

2.5 添加菜单

controller

直接调用mybatis-plus提供的方法:

/**
 * 新增菜单 √
 * @param permission
 * @return
 */@PostMapping("save")publicRsave(@RequestBodyPermission permission){
    permissionService.save(permission);returnR.ok();}

2.6 修改菜单

controller

根据菜单id修改菜单,直接调用mybatis-plus提供的方法:

/**
 * 修改菜单 √
 * @param permission
 * @return
 */@PutMapping("update")publicRupdateById(@RequestBodyPermission permission){//直接根据id修改
    permissionService.updateById(permission);returnR.ok();}

3.角色相关操作

3.1 获取角色分页列表

/**
 * 获取角色分页列表
 * @param page 当前页
 * @param limit 每页数量
 * @param role 查询的角色,根据名字模糊查询
 * @return
 */@GetMapping("{page}/{limit}")publicRindex(@PathVariableLong page,@PathVariableLong limit,Role role){//构造page对象Page<Role> pageParam=newPage<>(page,limit);//构造查询,如果有名字查询则进行like模糊查询LambdaQueryWrapper<Role> queryWrapper=newLambdaQueryWrapper<>();if(StringUtils.isNotBlank(role.getRoleName())){
        queryWrapper.like(Role::getRoleName,role.getRoleName());}//进行带条件的分页查询
    roleService.page(pageParam,queryWrapper);//返回最终的数据集合和总条数returnR.ok().data("items",pageParam.getRecords()).data("total",pageParam.getTotal());}

3.2 其他操作

根据id获取角色:

/**
 * 根据id获取角色
 *
 * @param id 角色id
 * @return
 */@GetMapping("get/{id}")publicRget(@PathVariableString id){Role role = roleService.getById(id);returnR.ok().data("item", role);}

新增角色:

/**
 * 保存角色
 *
 * @param role 角色对象
 * @return
 */@PostMapping("save")publicRsave(@RequestBodyRole role){
    roleService.save(role);returnR.ok();}

根据id修改角色:

/**
 * 根据id修改角色
 *
 * @param role
 * @return
 */@PutMapping("update")publicRupdateById(@RequestBodyRole role){
    roleService.updateById(role);returnR.ok();}

根据id删除角色:

/**
 * 根据id删除角色
 *
 * @param id
 * @return
 */@DeleteMapping("remove/{id}")publicRremove(@PathVariableString id){
    roleService.removeById(id);returnR.ok();}

批量删除角色:

/**
 * 批量删除角色
 *
 * @param idList 要删除角色的id集合
 * @return
 */@DeleteMapping("batchRemove")publicRbatchRemove(@RequestBodyList<String> idList){
    roleService.removeByIds(idList);returnR.ok();}

4.用户相关操作

4.1 获取管理用户分页列表

/**
 * 获取管理用户分页列表
 *
 * @param page        当前页
 * @param limit       每页数量
 * @param userQueryVo 查询条件,根据用户名字模糊查询
 * @return
 */@GetMapping("{page}/{limit}")publicRindex(@PathVariableLong page,@PathVariableLong limit,User userQueryVo){//构造page对象Page<User> pageParam =newPage<>(page, limit);构造查询,如果有名字查询则进行like模糊查询LambdaQueryWrapper<User> queryWrapper =newLambdaQueryWrapper<>();if(StringUtils.isNotBlank(userQueryVo.getUsername())){
        queryWrapper.like(User::getUsername, userQueryVo.getUsername());}//进行带条件的分页查询
    userService.page(pageParam, queryWrapper);//返回最终的数据集合和总条数returnR.ok().data("items", pageParam.getRecords()).data("total", pageParam.getTotal());}

4.2 根据用户获取角色数据

controller

/**
 * 根据用户获取角色数据
 * @param userId 用户id
 * @return
 */@GetMapping("/toAssign/{userId}")publicRtoAssign(@PathVariableString userId){Map<String,Object> roleMap = roleService.findRoleByUserId(userId);returnR.ok().data(roleMap);}
service

/**
 * 根据用户获取角色数据
 *
 * @param userId
 * @return
 */@OverridepublicMap<String,Object>findRoleByUserId(String userId){//1.查询所有的角色List<Role> roleList = baseMapper.selectList(null);//2.根据用户id查询对应UserRole对象List<UserRole> userRoleList = userRoleService.list(newLambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId).select(UserRole::getRoleId));//3.将UserRole对象等价转换为Role集合,这些角色就是该用户拥有的List<Role> resRoles = userRoleList.stream().map(e -> baseMapper.selectById(e.getRoleId())).collect(Collectors.toList());Map<String,Object> map =newHashMap<>();//4.告诉前端哪些是角色是该用户已经拥有的
    map.put("assignRoles", resRoles);//5.为了前端显示所有的角色
    map.put("allRolesList", roleList);return map;}

4.3 根据用户分配角色

controller

/**
 * 根据用户分配角色
 * @param userId 用户id
 * @param roleId 角色id集合
 * @return
 */@PostMapping("/doAssign")publicRdoAssign(@RequestParamString userId,@RequestParamString[] roleId){
    roleService.saveUserRoleRealtionShip(userId, roleId);returnR.ok();}
service

/**
 * 根据用户分配角色
 * @param userId
 * @param roleIds
 */@OverridepublicvoidsaveUserRoleRealtionShip(String userId,String[] roleIds){//分配前,先将原有的删除
    userRoleService.remove(newLambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId));List<UserRole> userRoleList =newArrayList<>();//遍历roleIds,一个个封装到UserRolefor(String roleId : roleIds){if(StringUtils.isEmpty(roleId))continue;UserRole userRole =newUserRole();
        userRole.setRoleId(roleId);
        userRole.setUserId(userId);
        userRoleList.add(userRole);}//批量保存
    userRoleService.saveBatch(userRoleList);}

4.4 其他操作

新增管理用户:

/**
 * 新增管理用户
 *
 * @param user
 * @return
 */@PostMapping("save")publicRsave(@RequestBodyUser user){//需要先把密码进行MD5加密在存入数据库
    user.setPassword(MD5.encrypt(user.getPassword()));
    userService.save(user);returnR.ok();}

根据id修改管理用户:

/**
 * 修改管理用户
 * @param user
 * @return
 */@PutMapping("update")publicRupdateById(@RequestBodyUser user){
    userService.updateById(user);returnR.ok();}

根据id删除管理用户:

/**
 * 删除管理用户
 * @param id
 * @return
 */@DeleteMapping("remove/{id}")publicRremove(@PathVariableString id){
    userService.removeById(id);returnR.ok();}

批量删除管理用户:

/**
 * 根据id列表删除管理用户
 * @param idList
 * @return
 */@DeleteMapping("batchRemove")publicRbatchRemove(@RequestBodyList<String> idList){
    userService.removeByIds(idList);returnR.ok();}

在这里插入图片描述

标签: 安全 dba linux

本文转载自: https://blog.csdn.net/qq_45966440/article/details/122746441
版权归原作者 LL.LEBRON 所有, 如有侵权,请联系我们删除。

“谷粒学院权限管理模块”的评论:

还没有评论