基于mybatis-plus的数据权限控制方案

1. 实现目标

以不侵入业务代码的方式实现数据权限控制,且能控制任意字段。

2. 实现思路

维护接口(Mapper中的标签id或者BaseMapper中的方法名)以及where条件,然后利用mybatis的拦截器读取配置并追加where条件。

3. 模块设计

分为两个模块:数据规则维护与数据权限分配

数据规则维护用来维护mapper名称、标签id以及where条件

数据权限分配用来为角色分配where条件

3.1 数据规则维护

3.1.1 查询页面

左侧为菜单树,右侧上方为mapper管理,下方维护where条件。

3.1.2 新增Mapper

先选则mapper,再选则mapper中对应的标签id,同时也可以维护BaseMapper中的方法。默认规则指的是一些通用规则,这些规则一般是过滤每张表都有的字段,比如 create_user_id,create_dept_id 等。

3.1.3 新增规则

规则类型分为字段和自定义类两种,为字段时,自己写where条件,为自定义类时,实现接口并注入到IOC容器中,配置beanId

3.2 权限分配

选角色、选刚刚创建的mapper、勾选规则,公式可以对规则进行组装

 4. 拦截器

拦截器中通过mapper+方法+登录人角色读取对应的公式,并将公式解析成 sql 片段,再利用 jsqlparser 进行拼接SQL。

5. 部分代码 

5.1 获取全部的mapper

public static Set<MapperDTO> getAllMapperList() {
	Set<MapperNameDTO> set = new HashSet<MapperNameDTO>();
	try {
		SqlSessionFactory sqlSessionFactory = SpringContextUtils.getBean(SqlSessionFactory.class);
		Collection<MappedStatement> mappedStatements = sqlSessionFactory.getConfiguration().getMappedStatements();

		for (Object mapped : mappedStatements) {
			if (mapped instanceof MappedStatement) {
				MappedStatement mappedStatement = (MappedStatement) mapped;
				String resource = mappedStatement.getResource();
				if (resource.contains("(best guess)")) {
					continue;
				}
				if (resource.startsWith("file")) {
					String id = mappedStatement.getId();
					String daoName = id.substring(0, id.lastIndexOf("."));
					daoName = daoName.substring(daoName.lastIndexOf(".") + 1);

					int i = resource.lastIndexOf(File.separator);
					set.add(new MapperDTO(resource.substring(i + 1, resource.length() - 1), daoName));
				}
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return set;
}

5.2  SQL 预览

public static Map<String, String> getSqlByMapperName(String mapperName) {
	Map<String, String> sqlMap = new HashMap<String, String>();
	try {
		SqlSessionFactory sqlSessionFactory = SpringContextUtils.getBean(SqlSessionFactory.class);
		Collection<MappedStatement> mappedStatements = sqlSessionFactory.getConfiguration().getMappedStatements();

		for (Object mapped : mappedStatements) {
			if (mapped instanceof MappedStatement) {
				MappedStatement mappedStatement = (MappedStatement) mapped;
				SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
				if ("SELECT".equals(sqlCommandType.toString())) {
					String id = mappedStatement.getId();
					String resource = mappedStatement.getResource();

					if (resource.contains("(best guess)")) {
						continue;
					}
					if (resource.startsWith("file")) {
						int i = resource.lastIndexOf(File.separator);
						String name = resource.substring(i + 1, resource.length() - 1);

						if (name.equals(mapperName)) {
							try {
								sqlMap.put(id.substring(id.lastIndexOf(".") + 1), mappedStatement.getBoundSql(null).getSql());
							} catch (Exception e) {
								continue;
							}
						}
					}
				}
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return sqlMap;
}

5.3  拦截器

@Override
public Object intercept(Invocation invocation) throws Exception {
	try {
		loginUserId = Static.sysUserAPI.getLoginUserId();
		if (!StringUtils.hasLength(loginUserId)) {
			return invocation.proceed();
		}

		Object[] obj = invocation.getArgs();
		MappedStatement ms = (MappedStatement) obj[0];
		mapperName = ms.getResource();
		if (mapperName.startsWith("file")) {
			mapperName = mapperName.substring(mapperName.lastIndexOf(File.separator) + 1, mapperName.length() - 1);
		} else {
			return invocation.proceed();
		}


		// 获得方法名称
		String sqlid = ms.getId();
		methodName = sqlid.substring(sqlid.lastIndexOf(".") + 1);

		// 校验模块是否需要被拦截,通过mapper + method + 用户ID,需要拦截则返回公式+方法id
		List<Map<String, Object>> formulaList = checkMapper(mapperName, methodName, loginUserId);

		if (!CollectionUtils.isEmpty(formulaList)) {
			// 拼接where条件
			splicingSelectSql(invocation, formulaList);
		}

		return invocation.proceed();
	} catch (Exception e) {
		StringWriter sw = new StringWriter();
		e.printStackTrace(new PrintWriter(sw));
		errorMsg = sw.toString();
		return invocation.proceed();
	}
}

5.4 拼接where条件

public static String splicingDefaulSelectSql(String oldSql, String whereSql) {
	try {
		Select select = (Select) CCJSqlParserUtil.parse(new StringReader(oldSql));
		SelectBody selectBody = select.getSelectBody();

		PlainSelect plainSelect = (PlainSelect) selectBody;
		Expression where = plainSelect.getWhere();
		if (null == where) {
			plainSelect.setWhere(new Column(whereSql));
		} else {
			plainSelect.setWhere(new AndExpression(new Parenthesis(where), new Column("(" + whereSql + ")")));
		}
		return select.toString();
	} catch (JSQLParserException e) {
		e.printStackTrace();
	}
	return oldSql;
}

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
SmartAdmin是一套互联网企业级的通用型中后台解决方案!使用最前沿的前后台技术栈SpringBoot和Vue,前后端分离,用一套漂亮的代码和一套整洁的代码规范,同时又让开发者节省大量的时间,减少加班,快乐工作,热爱生活。 技术体系: 前端:Vue + Vue-Router + Vuex + ViewUI(iview) + vue-enum 后端:SpringBoot2 + Mybatis-plus + jwt + druid + mysql 前端代码规范smart-front-standard -guide 基于阿里规范之上的后端规范smart-backend-standard-guide 理念与思想: 1、我们分享的不是代码,不是徒劳无功的堆砌功能,而是你必须的基础功能,比如Vue前端权限、心跳、动态Reload、Keepalived标签页等等,可能还有一些正是你当前项目中缺失的功能。 2、我们分享的不仅有代码,还有一套经过几十人验证过的前、后端代码。细节决定成败,好的规范能让我们敲下的每行代码更铿锵有力! 3、我们推崇高质量的代码,身为开发,代码即利剑,键盘上一套行云流水,宛如侠客,事了拂衣去,深藏身与名。 4、我们推崇团队的高度配合默契、互相帮助,从不加班,而不是一看到别人的代码就头皮发麻,留其996.ICU 5、我们热爱编程,热爱代码,保持谦逊,不断学习,快乐工作,热爱生活。 6、请相信并认真阅读下面的每一个点,让你感受不一样的编码体验 前端特点: 1、高质量的代码、代码结构、和代码注释 2、漂亮的UI,菜单栏、标签页等等 3、优化基于Keepalive的标签页,做到标签页该缓存的时候缓存,比如左右切换等,不该缓存的时候不缓存,比如新建,表单提交结束等 4、前端常量维护: vue-enum,拒绝出现魔法数字,代码不可维护的现象 5、全新的基于前端的权限设计(忘掉传统的权限设计吧,已经不适合这个前端时代) 6、体验、交互更好用的员工、部门、角色、菜单管理 7、基于websocket的在线人数 8、支持一级、二级、三级菜单 9、支持菜单搜索功能 10、其他功能:邮件、富文本、消息、系统配置等等 11、定时任务 12、写不完了,太多好的细节需要你的发现 后端特点: 1、高质量的Java代码、分包结构、和代码注释 2、业内独创的请求返回码维护,非常值得一看 3、基于一个注解和controller的权限设计放弃更复杂的shiro 4、完整的数据权限支持 5、四层架构(controller, service, manager, dao) 6、代码阅读性强、扩展性极高的员工、部门、角色、菜单管理 7、基于LRU策略的内存级权限缓存 8、自定义枚举表单验证,BigDecimal验证等 9、配合前端vue-enum的swagger文档注解 10、心跳服务,让你发现有哪些机器再跑,哪些人在偷偷的跑你的Job 11、自定义的quartz job添加和修改,方便测试人员测试 12、smart-reload,为系统预留钩子,动态加载,在不重启程序前提下执行一些代码,你懂的 13、其他功能:邮件、富文本、消息、系统配置等等 14、以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现! 前端代码规范: 1、文件、文件夹、目录结构、组建、变量等等怎么命名 2、html、css、less等如何规范 3、vue项目目录结构如何划分 4、router和store该怎么划分扩展性更好 5、vue组件规范该选择哪些 6、以及更多,数不胜数让你觉得实用,同时身心愉悦的规范 后端代码规范: 1、好多种分包,哪种更合理一些 2、四层架构(controller, service, manager, dao) 是什么,为什么要有四层 3、各个层的代码该怎么写才能让团队配合默契,高度一致 4、vo, bo, dto, entity 怎么区分和使用 5、spring的 @Transactional 你用对了吗 6、方法参数个数、注释、todo这些也要有规范,你遵守过吗 7、以上举例,只是沧海一粟,更多的细节等待你的发现! ps:以上规范基础都是以团队出发,让团队开心快乐的写代码,而不是为了代码规范而规范。
【资源说明】 毕业设计-基于知识图谱的科技政策管理系统python源码.zip 基础系统模块 系统功能模块组成如下所示: ``` ├─系统管理 │ ├─用户管理 │ ├─角色管理 │ ├─菜单管理 │ └─部门管理 ├─系统监控 │ ├─在线用户 │ ├─系统日志 │ ├─登录日志 │ ├─Redis监控 │ ├─Redis终端 │ ├─请求追踪 │ ├─系统信息 │ │ ├─JVM信息 │ │ ├─TOMCAT信息 │ │ └─服务器信息 ├─任务调度 │ ├─定时任务 │ └─调度日志 ├─代码生成 │ ├─生成配置 │ ├─代码生成 └─其他模块 ├─FEBS组件 │ ├─表单组件 │ ├─表单组合 │ ├─FEBS工具 │ ├─系统图标 │ └─其他组件 ├─APEX图表 ├─高德地图 └─导入导出 ``` 系统特点 **项目描述**:系统提供了完善的科技政策管理体系。通过参考现有的文本自动分类算法,使其能够完成科技政策的自动分类。提取科技政策的各种信息,完成多种条件相结合的检索方法。使用新词发现算法建立了科技政策的词典,同时配合文本分析算法,在一定程度上完成了科技政策之间的对比。采集大量科技政策建立有关科技政策的知识库,构成知识图谱,让政策与政策之间形成一定的关联。参考国务院发布的主题词表,确认了科技政策表达的主体内容。 **技术概述**:系统采用SpringBoot框架搭建,使用Shiro进行用户权限管理,实现单点登录,提高系统安全性。Redis统一缓存处理,提高系统性能和用户满意度,Hanlp文本处理并构建科技政策知识图谱网络图。 系统架构分为四个层次,分别为用户访问层、业务应用层、服务支撑层和数据存储层。用户层按用户的权限将用户分为三类,三类用户能够使用本系统的不同的功能。业务应用层主要包括科技政策查询,其中有政策文件查询、科技政策分类总览、科技政策知识图谱展示。科技政策分析中包括科技政策对比、演化和主题词分析以及智能问答,政策文件管理主要是政策类别管理。服务支撑层是该系统用到的主要方法,用来对数据进行加工。服务支撑层包括:文本自动分类、提取科技政策文本关键词、新词发现技术、知识图谱。数据存储层为系统提供数据,主要是保存科技政策文件的Mysql数据库和保存知识图谱的Neo4j数据库。 1、科技政策文件管理 # (1)科技政策查询 功能:用户根据自己的需要对科技政策进行检索和查看 输入数据:选择发布时间范围(可选),政策名称(可选),关键词(可选),发布单位(可选),全文检索(可选)。 输出结果:根据用户选择的查询条件,输入的政策名称,选择的时间范围,政策的发布机构,科技政策包含的关键词或包含的内容,在表格中以分页的形式进行展示,展示顺序按照发布时间倒序排序,在表格中显示的内容包括政策名称,政策发布日期和政策发布机构。 使用场景:用户知道某篇科技政策的具体或大概的名称,按照政策名称进行具体或模糊查询。想要寻找具体部门发布的科技政策,可以选择发布单位,按照单位条件进行内容检索。寻找包含某个关键词的科技政策可以按照关键词条件查找。 解决方案:通过用户点击查询按钮来获取用户的输入,将获取的输入传入到后台的控制类中,将获取的数据进行整理后传递给MyBatis-plus中相应的mapper,动态的创建SQL语句,之后使用MyBatis-plus的分页查询查件,到数据库中进行查询,将查询的数据转换成json格式,传递给Layui的table元素,解析json数据后以表格进行展示。 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
RuoYi-plus是一个基于RuoYi升级的springcloud版本管理系统。软件由SMP多商户后台管理系统+API后端接口组成,项目支持cms内容管理和商城业务,提供单机版服务、微服务体系双向选择,微服务集成分布式事务解决方案seata,框架基于SpringBoot2.x,springcloudG版本。 RuoYi-plus项目介绍 项目核心: 多商户权限系统+商城平台+CMS内容管理+微服务API系统 架构技术: 基于SpringBoot2.x, springcloud G版本eureka、hystrix、feign、config、gateway微服务架构体系的全新版本,集成分布式事务解决方案seata,集成redis、quartz、tk.mybatis、lombok、各种设计模式等。 项目优势: 架构更清晰、技术更前沿、代码更整洁、页面更美观、学习商用均可。可用于OA系统、 CRM系统、 PDM系统等二次开发,微服务架构学习,非常适用于公司管理平台旧版本升级、新平台搭建快速整合、同时提供API接口服务(供APP、微端、h5等使用)。 RuoYi-plus内置功能 管理平台基础功能 1、用户管理:用户是系统操作者,该功能主要完成系统用户配置。 2、部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 3、岗位管理:配置系统用户所属担任职务。 4、菜单管理:配置系统菜单,操作权限,按钮权限标识等。 5、角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 6、字典管理:对系统中经常使用的一些较为固定的数据进行维护。 7、参数管理:对系统动态配置常用参数。 8、通知公告:系统通知公告信息发布维护。 9、操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 10、登录日志:系统登录日志记录查询包含登录异常。 11、在线用户:当前系统中活跃用户状态监控。 12、定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 13、代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 14、系统接口:根据业务代码自动生成相关的api接口文档。 15、服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 16、在线构建器:拖动表单元素生成相应的HTML代码。 17、连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 商城业务基础功能 1、商户管理:多商户系统核心业务,商户管理对应权限数据。 2、类别管理:商品类别配置,为商品区分类别。 3、商品管理:每个商户下的商品信息。 CMS内容基础功能 1、文章类别管理:文章列表信息,为文章区分不同类别。 2、文章信息管理:文章具体信息,直接生成文章html页面。 3、素材类别管理:为素材提供类别以区分不同业务的素材图片/视频。 4、素材信息管理:文章信息的素材图片管理。 API接口基础功能 1、业务模块:接收网关gateWay转发请求,api微服务结构处理具体业务,解决分布式事务。 2、订单模块:订单相关业务处理。 3、商品模块:商品相关业务处理。 商用须知 本项目遵循MIT协议,无需授权,留言备注公司信息即可。 演示地址账号:tecom  密码:123456

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值