IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【清晨平台记录六】代码实现平台后台用户模块四(主要实现操作权限、数据权限的过滤) -> 正文阅读

[Java知识库]【清晨平台记录六】代码实现平台后台用户模块四(主要实现操作权限、数据权限的过滤)

上一篇地址:【清晨平台记录五】代码实现平台后台用户模块三(主要实现登录账号信息、操作权限内容)

本篇代码地址:Gitee 地址 注意是 project06 分支哦

接口文档地址:Apifox工具编写的接口文档

目录

5.用户模块—研发思路

5.2子模块研发

5.2.7操作权限、数据权限

1.操作权限

2.数据权限

后续的模块~~


5.用户模块—研发思路

5.2子模块研发

5.2.7操作权限、数据权限

1.操作权限

操作权限从设计的角度来说,就是用户使用系统时,能够展示并使用哪些导航栏、页面、按钮。

有两种形式:

一种是后端返回用户权限集合后,用户操作时,由前端判断当前操作权限是否包含在用户权限集合中,后端不做判断处理。

一种是后端返回用户权限集合后,用户操作时,前端直接调用相应后端接口,由后端判断当前操作权限是否包含在用户权限集合中,前端不做判断处理。

第一种有一个问题,用户正常使用时不会出现问题,但是如果有用户了解平台的接口调用规则,直接调用接口(通过Apifox等),就可以直接无权限访问!这是不可以的,所以建议后端一定要做操作权限判断!

而我们使用 springSecurity 工具框架,他就为我们提供了这样的工具,我们直接使用就可以,灵活又方便~~~

我们主要是用 springSecurity 的权限注解,自定义调用权限校验的方式 :@PreAuthorize("@serviceBeanName.hasPermi('system:user:list')")

这个注解是添加到接口方法上的,当接口被访问时,会先调用 bean 名字为?serviceBeanName 的 .hasPermi(参数) 的方法,方法的返回值是?boolean ,如果是 true 则表示权限校验通过,如果是 false 则表示权限校验失败 。

也就是说,我们需要提前获取到当前用户都有哪些权限(即权限标识)集合,然后写一个验证权限的service业务类,需要将当前访问接口需要的权限作为入参传进来,然后判断入参在不在权限集合里面,若在则返回true,不择则返回false,最后再将这个注解添加到需要验证权限的接口方法上面~

开始码代码:

//我们在 admin 模块中写表现层
 
1.实体类
	登录用户类:com.qingchen.common.core.domain.model.LoginUser implements UserDetails 
		添加一个 set 集合permissions ,里面保存当前账号所有启用的操作权限的标识集合
		
2.业务层
	加载用户信息类ServiceImpl:com.qingchen.framework.web.service.UserDetailsServiceImpl implements UserDetailsService
		我们需要在用户登录的时候给登录用户类里的权限集合添加数据
	
	校验权限类service:com.qingchen.framework.web.service.PermissionService
		我们在接口上加的注解中调用的bean方法就是这个类里面的
		
3.配置类
	security配置类:com.qingchen.framework.config.SecurityConfig extends WebSecurityConfigurerAdapter
		如果使用security的表达式控制方法权限,就需要加上 @EnableGlobalMethodSecurity(prePostEnabled = true)注解
		
4.表现层(给需要授权的接口方法加上,对应的权限注解,这里举个栗子)
	用户表现类:com.qingchen.controller.system.SysUserController extends BaseController
	

// 我们给新增和修改方法,加上注解,注意这里的权限标识'system:user:list',需要和数据库 sys_menu 表里的标识对应!
// @PreAuthorize("@permissionService.hasPermi('system:user:list')")

测试之前,我们需要搭建一下测试数据~

首先需要完整的 sys_menu 表数据,然后创建角色,并给角色选择性绑定菜单权限,然后给用户绑定角色。

可以测试没有这个权限的用户访问结果,和有这个权限的用户访问结果来对比:

这是没有权限时的访问


2.数据权限

操作权限从设计的角度来说,就是用户使用系统时,如果打开了一个列表的页面,那么会根据他的对于这个列表的数据范围获取到的相应的创建的数据。

对于设计而言,每个角色对应一个菜单权限和数据权限,数据权限只针对于当前角色里面的菜单权限。如果一个用户有多个角色,角色里面的菜单权限有重复的,那么这些重复的菜单的数据权限按照并集处理(也就是按照最大的范围获取)。

数据权限范围有大到小为:1.全部,2.自定义用户组,3.当前用户组,4.当前用户组及其子用户组,5.仅自己。

举个例子:

下图中,如果用户打开了菜单管理页面,它能够查询到的数据范围是全部创建的(全部 > 仅自己),如果他打开用户管理页面,他能够查询到的数据范围是本用户组创建的(本用户组 > 仅自己),以此类推。

也就是说,获取某个页面的列表时,先根据当前访问的菜单列表权限,从拥有这个菜单权限的角色集合中判断一个最大角色范围,按照这个最大的角色范围去获取数据。

也就是说,当我们获取需要区分数据范围的列表数据时,我们先给菜单类型的数据一个标识,当我们访问这个菜单对应的列表查询的业务层时,先根据这个菜单标识,查询用户绑定的角色中,哪些角色有这个菜单权限,然后从这些角色中获取一个范围最大的数据范围,根据这个范围去获取数据~

注意,我们需要通过菜单标识,获取一个能确认唯一一个菜单类型的菜单,这里我们选择用?perm?字段来获取,为什么不用?menu_id?呢?因为菜单可能会删除,删除后代码里的判断就无效啦,并且某个菜单的权限逻辑是不会轻易改变的,所以他的标识也不会轻易改变!并且菜单的权限标识也应该唯一的,不能够重复,否则就定位不到了。

(所以我们记得在新增、修改菜单时,判断菜单权限标识是否唯一,并且,在判断操作权限的hasPermi(String permission)方法基础上,在再增加一个可以判断多权限的方法 hasPermi(String[]?permission) )

我们使用切面编程来实现数据权限,这样就不会影响到方法内部的逻辑了,我们想要给某个方法加上这个逻辑,就直接定位到这个方法就行了。定位方法我们用注解的方式,这样直接给方法加上注解就行啦!

再一个,我们拼接了mybatis 动态查询的语句后,需要传给 mapper ,我们就需要从切面类回传给service,可以通过反向代理拿到业务方法的入参,然后将动态语句传给入参,这样业务方法就能够获取到动态语句啦!这样我们就需要给业务方法添加一个入参,专门存放动态语句,这样就可能就需要给所有需要判断数据权限的方法都加上入参,破坏性太大!

通常情况,我们查询时都会传当前类型的实体类,那么我们就可以将动态接收的语句存到每个实体类里面,也就是实体基类!

开始码代码:

//我们在 admin 模块中写表现层
 
1.注解类
	数据范围注解:com.qingchen.common.annotation.DataScope
		我们传一个菜单类型的菜单权限标识,来确定菜单的唯一性
		
		
2.切面类
	数据范围注解切面类:com.qingchen.framework.aspect.DataScopeAspect
		根据切点传过来的菜单权限标识,确定数据范围,然后if判断加上对应的动态mybatis语句,并将动态语句存到入参实体类的基类的字段里面


3.实体类
	实体基类:com.qingchen.common.core.domain.BaseEntity implements Serializable
		添加一个专门存放动态语句的字段,在 get 方法里加个判断,若是 null 则 new 一个对象出来,防止 NullPointerException 错误
		
		
4.业务层
	角色service:com.qingchen.system.service.impl.SysRoleServiceImpl implements SysRoleService
		因为我们要查询当前菜单在用户的角色集合中的哪些角色存在,并对比出数据范围优先级最大的范围
	
	菜单service:com.qingchen.system.service.impl.SysMenuServiceImpl implements SysMenuService
		这里要在菜单新增编辑的时候判断权限标识的唯一性,
		
	校验权限service:com.qingchen.framework.web.service.PermissionService
		这里要再添加一个判断多权限的方法
		
		
5.持久层(给需要判断数据权限的查询语句加上必要的关联表,这里拿查询用户举个栗子)
	角色mapper:com.qingchen.system.mapper.SysRoleMapper
				mapper/system/SysRoleMapper.xml
		添加新增加的SQL语句,修改用户组select语句
		
	用户mapper:mapper/system/SysUserMapper.xml
		给相关的查询语句添加必要的关联表<select id="selectUserList"
		

6.业务层
	用户组service:com.qingchen.system.service.impl.SysUserServiceImpl implements SysUserService
		给查询用户列表的方法加上注解:@DataScope( perm = "system:user:list")





准备测试数据:

首先我们需要 6 个角色,其中 5 个角色都有 “system:usergroup:list”的菜单权限,并且数据范围是从全部到仅自己,角色名用1-5表示;最后一个角色不包含 “system:usergroup:list”的菜单权限,数据范围随机(例如全部),角色名用 6 表示

然后,我们创建 6 个用户,并且将用户的创建人分别设置为自己。然后再创建 5 个用户组,并给他们分别绑定用户。就像下面的结构:

- 用户组1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 绑定用户:yonghu1

????????- 用户组11? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 绑定用户:yonghu11 、yonghu110

????????????????- 用户组111????????????????????????????????????绑定用户y:yonghu111

????????- 用户组12?????????????????????????????????????????????绑定用户:yonghu12

- 用户组2????????????????????????????????????????????????????????绑定用户:yonghu2

最后,我们给角色 2 绑定 用户组1、用户组12、用户组111? 三个用户组。

【以上数据都是同一个用户名下的哦~】

注意哦,登录后先通过 getInfo() 接口获取用户信息,拿到用户权限标识,否则直接调用获取用户列表是会提示没权限的!

而且测完一项记得重新登陆获取token,否则redis里的角色信息是不会变的!

我们使用 yonghu11 账号进行获取用户列表测试,按照下面的测试:

目标测试

用户角色预期(描述能查到哪个用户创建的用户)
全部yonghu11(用户组11)1,2,3,5,6能查询所有的
自定义yonghu112,4,5,6能查询到yonghu 1、12、111
本用户组yonghu113,5,6只能查到 yonghu 11、110
本用户组及其子级yonghu114,5,6能查到yonghu 11、110
仅自己yonghu115,6只能查到 yonghu 11?

测试每一项前,只需要修改用户关联的角色就可以,例如测试本用户组时,设置 yonghu11 关联的角色为 上方说明的 3,5,6 (也就是数据库角色表里名为 用户查看(3本用户组) 、用户查看(5仅自己)、菜单管理6的角色),那么数据范围最终定位的就是 3 本用户组。

完成~


后续的模块~~

5.2.8列表分页

5.2.9角色模块添加操作用户的逻辑

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:38:23  更:2022-07-20 18:41:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:00:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码