文章目录

  • 谷粒学院项目权限管理模块
    • 1.数据库表
    • 2.菜单相关操作
      • 2.1 递归查询全部菜单
      • 2.2 递归删除菜单
      • 2.3 给角色分配权限
      • 2.4 根据角色获取菜单
      • 2.5 添加菜单
      • 2.6 修改菜单
    • 3.角色相关操作
      • 3.1 获取角色分页列表
      • 3.2 其他操作
    • 4.用户相关操作
      • 4.1 获取管理用户分页列表
      • 4.2 根据用户获取角色数据
      • 4.3 根据用户分配角色
      • 4.4 其他操作

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

1.数据库表

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

RBAC模型

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

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

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

  • 菜单表acl_permission

  • 角色表acl_role

  • 用户表acl_user

  • 角色—菜单表acl_role_permission

  • 用户—角色表acl_user_role

几个表之间的关系:

2.菜单相关操作

2.1 递归查询全部菜单

controller

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

service

/*** 递归查询所有菜单** @return*/
@Override
public List<Permission> queryAllMenuGuli() {//1.查询菜单表所有数据LambdaQueryWrapper<Permission> queryWrapper = new LambdaQueryWrapper<>();//按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*/
public static List<Permission> bulidPermission(List<Permission> permissionList) {//1.创建list集合,用于数据最终封装List<Permission> finalNode = new ArrayList<>();//2.把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1for (Permission permission : permissionList) {//得到顶层菜单 pid=0菜单if ("0".equals(permission.getPid())) {//设置顶层菜单的level是1permission.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*/
private static Permission selectChildren(Permission permissionNode, List<Permission> permissionList) {//因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化permissionNode.setChildren(new ArrayList<Permission>());//遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同,是不是当前菜单的子菜单for (Permission permission : permissionList) {//当前菜单的pid=上级菜单idif (permission.getPid().equals(permissionNode.getId())) {int level = permissionNode.getLevel() + 1;//设置当前菜单level为父菜单level+1permission.setLevel(level);//设置子菜单,子菜单依然需要递归查询子菜单是否也有子菜单permissionNode.getChildren().add(selectChildren(permission, permissionList));}}return permissionNode;
}

2.2 递归删除菜单

controller

/*** 递归删除菜单 √* @param id* @return*/
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {permissionService.removeChildByIdGuli(id);return R.ok();
}

service

/*** 递归删除菜单** @param id 菜单id*/
@Override
public void removeChildByIdGuli(String id) {//1.创建list集合,用于封装所有删除菜单id值List<String> idList = new ArrayList<>();//2.加入所有子菜单的idthis.selectPermissionChildById(id, idList);//3.加入自己的ididList.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集合*/
private void selectPermissionChildById(String id, List<String> idList) {LambdaQueryWrapper<Permission> queryWrapper = new LambdaQueryWrapper<>();//1.查询菜单里面子菜单idqueryWrapper.eq(Permission::getPid, id);//2.只需要idqueryWrapper.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")
public R doAssign(String roleId,String[] permissionId) {permissionService.saveRolePermissionRealtionShipGuli(roleId,permissionId);return R.ok();
}

service

/*** 角色分配菜单** @param roleId        角色id* @param permissionIds 菜单id集合*/
@Override
public void saveRolePermissionRealtionShipGuli(String roleId, String[] permissionIds) {//1.创建list集合,用于封装添加数据List<RolePermission> permissionList = new ArrayList<>();for (String permissionId : permissionIds) {if (StringUtils.isEmpty(permissionId)) continue;RolePermission rolePermission = new RolePermission();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}")
public R toAssign(@PathVariable String roleId) {List<Permission> list = permissionService.selectAllMenu(roleId);return R.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*/
@Override
public List<Permission> selectAllMenu(String roleId) {//1.查询所有Perssion,并按id排序List<Permission> permissionList = baseMapper.selectList(new LambdaQueryWrapper<Permission>().orderByDesc(Permission::getId));//2.根据roleId查询在acl_role_permission表里查询所有RolePerssionList<RolePermission> rolePermissionList = rolePermissionService.list(new LambdaQueryWrapper<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为truepermissionList.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")
public R save(@RequestBody Permission permission) {permissionService.save(permission);return R.ok();
}

2.6 修改菜单

controller

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

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

3.角色相关操作

3.1 获取角色分页列表

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

3.2 其他操作

根据id获取角色:

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

新增角色:

/*** 保存角色** @param role 角色对象* @return*/
@PostMapping("save")
public R save(@RequestBody Role role) {roleService.save(role);return R.ok();
}

根据id修改角色:

/*** 根据id修改角色** @param role* @return*/
@PutMapping("update")
public R updateById(@RequestBody Role role) {roleService.updateById(role);return R.ok();
}

根据id删除角色:

/*** 根据id删除角色** @param id* @return*/
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {roleService.removeById(id);return R.ok();
}

批量删除角色:

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

4.用户相关操作

4.1 获取管理用户分页列表

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

4.2 根据用户获取角色数据

controller

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

service

/*** 根据用户获取角色数据** @param userId* @return*/
@Override
public Map<String, Object> findRoleByUserId(String userId) {//1.查询所有的角色List<Role> roleList = baseMapper.selectList(null);//2.根据用户id查询对应UserRole对象List<UserRole> userRoleList = userRoleService.list(new LambdaQueryWrapper<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 = new HashMap<>();//4.告诉前端哪些是角色是该用户已经拥有的map.put("assignRoles", resRoles);//5.为了前端显示所有的角色map.put("allRolesList", roleList);return map;
}

4.3 根据用户分配角色

controller

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

service

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

4.4 其他操作

新增管理用户:

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

根据id修改管理用户:

/*** 修改管理用户* @param user* @return*/
@PutMapping("update")
public R updateById(@RequestBody User user) {userService.updateById(user);return R.ok();
}

根据id删除管理用户:

/*** 删除管理用户* @param id* @return*/
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {userService.removeById(id);return R.ok();
}

批量删除管理用户:

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

谷粒学院权限管理模块相关推荐

  1. 谷粒学院订单管理 server-order 模块

    谷粒学院订单管理 server-order 模块 模块介绍 主要实现前台页面购买课程后,生成订单,并实现微信支付的功能. ![]](https://img-blog.csdnimg.cn/7b821f ...

  2. Expo大作战(三十)--expo sdk api之Permissions(权限管理模块),Pedometer(计步器api)

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  3. 一个权限管理模块的设计(转载)

    一 个用户权限管理模块的设计思路: 1. 权 限资源(功能资源) 系统的所有权限信息.权限具有上下级关系,是一个树状的结构.如下: <!--[if !supportLists]-->u  ...

  4. 一个简易实用的web权限管理模块的应用与实现

    本文介绍一个简易实用的web权限管理模块的应用与实现. 先介绍数据模型和应用界面,后继对实现细节做选择性阐述. 数据表关系如下: 该图标明了登陆用户.角色.部门(机构).用户组.角色和模块功能之间的关 ...

  5. Yii框架中使用SRBAC作为权限管理模块时遇到的问题

    Yii框架中使用SRBAC作为权限管理模块时遇到的问题 Yii框架中使用SRBAC作为权限管理模块时遇到的问题 看到Yii中提供RBAC的插件,SRBAC,就想用用. 结果按照手册上的安装办法,整来整 ...

  6. 6. 添加权限管理模块

    本文主要是以权限管理模块为例来介绍使用springboot+mybatis完成增删改查的功能. 1. 添加Permission实体类 1 package com.lvniao.blog.model; ...

  7. 通俗易懂权限管理模块设计-Java

    最近一直在做CMS系统,发现一些内容其实都是重复出现的,例如权限管理模块.权限管理模块就是为了管理用户是否有权利访问某个权限,如果不能则拒绝访问.其实Java中已经有很成熟的权限管理框架,例如 Shi ...

  8. 谷粒学院——后台管理系统功能模块

    在线教育 普通用户前台使用系统 管理员后台管理系统 讲师管理模块 环境搭建 讲师列表查询 讲师删除(逻辑删除) 整合swagger 统一结果数据返回 分页查询讲师 新增讲师 统一异常处理 日志 登录功 ...

  9. 如何设计一个权限管理模块?

    我们每天都在使用各种各样的办公自动化系统,也叫OA.ERP系统.不同的用户登录能看到的菜单和数据资源都不一样. 比如,管理员登入财务系统,能看见员工模块,员工登录就看不见,这就是菜单权限:员工登录财务 ...

  10. Java代码生成器codeMan重磅更新——添加权限管理模块生成功能,实现动态菜单和按钮级别的权限控制

    前言 转眼又过去了两个多月,时间就像一个隐形的精灵,总是在不经意间从眼皮底下溜走,不知不觉已经8月底了,金九银十近在眼前,不知道小伙伴们有没有跳槽的打算呢?相信此时你的心中已经有了自己的答案.闲言少叙 ...

最新文章

  1. 自动添加端口添加至Windows防火墙脚本
  2. 【小白学习PyTorch教程】十九、 基于torch实现UNet 图像分割模型
  3. linux通过c语言编程访问远程mysql
  4. destroy 方法_线程方法destroy()和stop(Throwable)在JDK 11中删除
  5. MySQL学习(三)
  6. 对比 SQL Server 2005 和 Oracle
  7. c++ 字符串转数字
  8. ESP32开发 0.windows Vscode开发环境搭建,基于esp-idf-V4.2 | Cmake | Vscode插件
  9. IE浏览器使用Validation Engine表单重复提交问题
  10. 常用RAID类型以及它们的区别
  11. Android每日一记
  12. Leetcode 122.买卖股票的最佳时机II
  13. php 打印所有常量,php中输出常量
  14. linux最新的发布版本号,求问Linux最新内核版本以及发布日期。
  15. 关于attachEvent与addEventListener事件绑定兼容问题
  16. 联想笔记本prtsc不能截图_Win10系统下怎么截屏
  17. 攻防世界 REVERSE 新手区/logmein
  18. 【12306购票】测试运行以及完整代码
  19. 如何修改PDF中图片的大小尺寸
  20. 如何解决浏览器提示“您与此网站之间建立的连接不安全”

热门文章

  1. 目标检测->SSD算法
  2. 【bat批处理脚本命令】bat命令接收用户输入的内容(保姆级图文+实现代码)
  3. 10个python经典小游戏(上)-五一嗨起来(动图演示+源码分享)
  4. Linux安装GCC 9.2.0
  5. C语言练习——百钱百鸡
  6. git 小乌龟 配置_git 小乌龟安装教程
  7. TP5框架开发 很不错的小程序商城源码!免费开源
  8. Windows解决net Framerwork 3.5无法安装的问题
  9. 计算机组成原理(白中英) 第七章 课后题答案
  10. 火山PC_POST教程