MyBatis-plus sql拦截器

因为业务需求,重新写了一套数据权限。项目中用的是mybtis-plus,正好MyBatis-Plus提供了插件数据权限插件 | MyBatis-Plus,那就根据文档来实现这个需求。

实现:

实现MultiDataPermissionHandler

首先创建MultiDataPermissionHandler的实现类,里面的内容自己做校验

@Slf4j
public class CustomDataPermissionHandler implements MultiDataPermissionHandler {// 岗位idprivate static final String CEO = "1";private static final String SE = "2";private static final String HR = "3";private static final String USER = "4";// 免校验表private static final String SYS = "sys";private static final Set<String> EXEMPT_TABLES = Set.of("xxx不过滤的表","xxx不过滤的表");@Overridepublic Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {try {if (IgnoreWhereConditionAspect.shouldIgnoreWhereCondition()) {return null;}// 免校验表if (isExemptTable(table.getName())) {return null;}// 获取当前用户 未登录不做校验SysUser user = getCurrentUser();if (user == null || user.isAdmin()) {return null;}/* 获取岗位ids,总管可以看全部数据,主管可以看到自己小组的数据,其他只可以看到自己的数据 */List<String> postIds = getUserPostIds(user);if (postIds.contains(CEO)) {return null;}return postIds.contains(SE) ? parseGroupDataExpression(user.getGroupId(), getTableName(table)) : parseOwnDataExpression(getTableName(table));} catch (JSQLParserException e) {log.error("数据权限过滤失败," ,e);return null;}}/*** 获取表名* @param table 表* @return 表名*/private String getTableName(Table table) {return String.valueOf(table.getAlias() == null ? table.getName() : table.getAlias().getName());}/*** 获取用户岗位ids* @param user 当前操作的用户* @return 岗位ids*/private List<String> getUserPostIds(SysUser user) {if (user.getPostIds() == null) {throw new ServiceException(POST_MUST_NOT_NULL);}return Arrays.asList(user.getPostIds());}/*** 获取当前用户* @return 当前用户*/private SysUser getCurrentUser() {try {return SecurityUtils.getUser();} catch (Exception e) {return null;}}/*** 根据表名判断是否免校验* @param tableName 表名* @return 是否免校验*/private boolean isExemptTable(String tableName) {return tableName.startsWith(SYS) || EXEMPT_TABLES.contains(tableName);}/*** 解析组数据表达式* @param groupId 组id* @return 组数据表达式*/private Expression parseGroupDataExpression(String groupId, String tableName) throws JSQLParserException {return CCJSqlParserUtil.parseCondExpression(tableName + ".create_by in (select sug.user_id from sys_user su " +"join sys_user_group sug on sug.user_id = su.id " +"where sug.group_id = " + groupId + ")");}/*** 解析自己的数据表达式* @return 自己的数据表达式*/private Expression parseOwnDataExpression(String name) throws JSQLParserException {return CCJSqlParserUtil.parseCondExpression(name + ".create_by = " + SecurityUtils.getUserId());}

这里实现了MultiDataPermissionHandler接口的getSqlSegment方法,根据文档说明不需要拼接where条件的直接返回null就可以,需要拼接where添加的拼接相应的条件

注册数据权限拦截器

@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 分页插件interceptor.addInnerInterceptor(paginationInnerInterceptor());// 乐观锁插件interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());// 阻断插件interceptor.addInnerInterceptor(blockAttackInnerInterceptor());// 数据权限插件interceptor.addInnerInterceptor(new DataPermissionInterceptor(new CustomDataPermissionHandler()));return interceptor;}/*** 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html*/public InnerInterceptor paginationInnerInterceptor() {PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();// 设置数据库类型为mysqlpaginationInnerInterceptor.setDbType(DbType.MYSQL);// 设置最大单页限制数量,默认 500 条,-1 不受限制paginationInnerInterceptor.setMaxLimit(-1L);return paginationInnerInterceptor;}/*** 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html*/public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {return new OptimisticLockerInnerInterceptor();}/*** 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html*/public InnerInterceptor blockAttackInnerInterceptor() {return new BlockAttackInnerInterceptor();}
}

新建注解IgnoreWhereCondition

表示是否忽略sql拦截,默认为true,如果有些接口不需要鉴权就在controller上添加这个注解

@Target(ElementType.METHOD) // 该注解应用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时可用
public @interface IgnoreWhereCondition {boolean value() default true; // 默认值为 true,表示忽略
}

新建AOP切面 IgnoreWhereConditionAspect

/*** AOP切面,用于处理带有 @IgnoreWhereCondition 注解的方法。* 通过ThreadLocal存储当前方法是否需要忽略SQL拦截的状态。*/
@Aspect
@Component
public class IgnoreWhereConditionAspect {private static final ThreadLocal<Boolean> ignoreWhereConditionHolder = ThreadLocal.withInitial(() -> false);/*** 在方法执行前检查是否有 @IgnoreWhereCondition 注解,并设置ThreadLocal中的状态。* @param joinPoint JoinPoint*/@Before("@annotation(com.sh.framework.annotation.IgnoreWhereCondition)")public void beforeMethod(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();IgnoreWhereCondition annotation = method.getAnnotation(IgnoreWhereCondition.class);ignoreWhereConditionHolder.set(annotation.value());}/*** 获取当前线程中是否应该忽略SQL拦截。* 如果需要忽略,则清除ThreadLocal中的状态。* @return boolean*/public static boolean shouldIgnoreWhereCondition() {Boolean b = ignoreWhereConditionHolder.get();if (b) clear();return b;}public static void clear() {ignoreWhereConditionHolder.remove();}
}

使用注解

@SelectRecordAnnotate(value = "分页查询付款申请")
@Operation(summary = "分页查询付款申请")
@GetMapping("selectPage")
@IgnoreWhereCondition
public AjaxResult selectPage(SiHePage page, CostPayReqVO costPayReqVO) {return success(costPayReqService.selectListPage(page, costPayReqVO));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/501748.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据挖掘——关联规则挖掘

数据挖掘——关联数据挖掘 关联数据挖掘关联规则关联规则挖掘问题&#xff1a;具体挖掘过程Apriori 产生关联规则 关联数据挖掘 关联分析用于发现隐藏在大型数据集中的令人感兴趣的联系&#xff0c;所发现的模式通常用关联规则或频繁项集的形式表示。 关联规则反映一个事物与…

启航数据结构算法之雅舟,悠游C++智慧之旅——线性艺术:顺序表之细腻探索

人无完人&#xff0c;持之以恒&#xff0c;方能见真我&#xff01;&#xff01;&#xff01; 共同进步&#xff01;&#xff01; 文章目录 一、线性表的概念二、顺序表1.概念与结构2.顺序表的分类静态顺序表动态顺序表 三、顺序表的实现1.顺序表的结构2.顺序表的初始化和销毁初…

数据库进阶教程之DDL语句(万字详解)

文章目录 一、数据库操作-上1.1、DDL概述1.2、创建数据库1.3、查看数据库 二、数据库操作-下2.1、修改数据库2.2、删除数据库2.3、使用数据库 三、数据库表操作-上3.1、创建表3.2、数据类型&#xff08;mysql&#xff09;3.3、查看表 四、数据库表操作-中4.1、快速建表4.2、删除…

自动驾驶三维重建

大概八成估计是未来的科研方向了 文章目录 自动驾驶中的NeRF[4]CLONeR&#xff1a;Urban Radiance Fields[6]S-NERFBlock-NeRFSwitch-NeRFSceneRFBehind the Scenes 大规模与自动驾驶场景重建:3D高斯VastGaussianPeriodic Vibration Gaussian&#xff08;复旦大学&#xff09;…

OWASP ZAP之API 请求基础知识

ZAP API 提供对 ZAP 大部分核心功能的访问,例如主动扫描器和蜘蛛。ZAP API 在守护进程模式和桌面模式下默认启用。如果您使用 ZAP 桌面,则可以通过访问以下屏幕来配置 API: Tools -> Options -> API。 ZAP 需要 API 密钥才能通过 REST API 执行特定操作。必须在所有 …

【小程序开发】- 小程序版本迭代指南(版本发布教程)

一&#xff0c;版本号 版本号是小程序版本的标识&#xff0c;通常由一系列数字组成&#xff0c;如 1.0.0、1.1.0 等。版本号的格式通常是 主版本号.次版本号.修订号 主版本号&#xff1a;当小程序有重大更新或不兼容的更改时&#xff0c;主版本号会增加。 次版本号&#xff1a…

电子应用设计方案85:智能 AI门前柜系统设计

智能 AI 门前柜系统设计 一、引言 智能 AI 门前柜系统旨在提供便捷、安全和智能的物品存储与管理解决方案&#xff0c;适用于家庭、公寓或办公场所的入口区域。 二、系统概述 1. 系统目标 - 实现无接触式物品存取&#xff0c;减少交叉感染风险。 - 具备智能识别和分类功能&am…

CG顶会论文阅读|《科技论文写作》硕士课程报告

文章目录 一、基本信息1.1 论文基本信息1.2 课程基本信息1.3 博文基本信息 二、论文评述&#xff08;中英双语&#xff09;2.1 研究问题&#xff08;Research Problem&#xff09;2.2 创新点&#xff08;Innovation/Contribution&#xff09;2.3 优点&#xff08;Why this pape…

Deepseek v3 的笔记

基本概述 Deepseek v3是Deepseek发布的旗舰模型&#xff0c;属于607B的混合专家&#xff08;MoE&#xff09;模型&#xff0c;其中活跃参数为37B。在当前的模型领域&#xff0c;它堪称最佳的开源模型&#xff0c;性能超越了Llama 3.1 405b、Qwen和Mistral等知名模型。根据基准…

基于单片机的家庭智能垃圾桶(论文+源码)

1系统整体方案设计 本次课题为基于单片机的家庭智能垃圾桶&#xff0c;在此将目标功能设计如下&#xff1a; &#xff08;1&#xff09;实现垃圾桶的智能开关盖当检测到有人停留三秒以上自动开启&#xff0c;并当人走后自动关闭开关盖&#xff1b; &#xff08;2&#xff0…

Niushop商城商业插件_cps联盟_包装转换_视频购物_同城配送_上门预约等插件的安装方法

一.简介 使用Niushop已经多年&#xff0c;积累下很多有用的常识&#xff0c;有人让我评价下这个系统&#xff01;怎么说呢&#xff01;系统是好系统因为它开源&#xff01;且更新也很及时几乎是一周一更新&#xff0c;开发团队也很尽职&#xff0c;在用户群内得到很高的评价&am…

一文讲清楚HTTP常见的请求头和应用

文章目录 一文讲清楚HTTP常见的请求头和应用1. 啥是个HTTP请求头2. 常见的请求头&#xff0c;作用和示例3.协商缓存4.会话状态 一文讲清楚HTTP常见的请求头和应用 1. 啥是个HTTP请求头 一句话&#xff0c;说白了就是限定HTTP传输的一些规则参数&#xff0c;比如Accept&#xf…

vim 的基础使用

目录 一&#xff1a;vim 介绍二&#xff1a;vim 特点三&#xff1a;vim 配置四&#xff1a;vim 使用1、vim 语法格式2、vim 普通模式&#xff08;1&#xff09;保存退出&#xff08;2&#xff09;光标跳转&#xff08;3&#xff09;文本删除&#xff08;4&#xff09;文本查找&…

RocketMQ面试题:进阶部分

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

设计模式之桥接设计模式

简介 与适配器模式类似&#xff0c;桥接设计模式也是结构型模式将抽象部分与实现部分分离&#xff0c;使它们都可以独立的变化通俗来说&#xff0c;是通过组合来桥接其它的行为/维度 应用场景举例 传统方式 使用桥接设计模式之后 编码示例 /*** 抽象角色&#xff1a;手机*/ …

个人健康信息系统|Java|SSM|VUE| 前后端分离

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库可…

个人交友系统|Java|SSM|JSP|

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、JSP、jquery,html 5⃣️数据库可…

每天40分玩转Django:Django Celery

Django Celery 一、知识要点概览表 模块知识点掌握程度要求Celery基础配置、任务定义、任务执行深入理解异步任务任务状态、结果存储、错误处理熟练应用周期任务定时任务、Crontab、任务调度熟练应用监控管理Flower、任务监控、性能优化理解应用 二、基础配置实现 1. 安装和…

canvas+fabric实现时间刻度尺+长方形数据展示

前言 我们前面实现了时间刻度尺&#xff0c;现在在时间刻度尺里面画一个长方形&#xff0c;长方形里面有数据展示。 效果 实现 1.先实现时间刻度尺 2.鼠标移动、按下事件监听并画出对应效果 3.在刻度尺里面画对应的长方形数据展示 <template><div><canvas…

网络安全【C10-2024.10.1】-sql注入基础

1、利用宽字节注入实现“库名-表名”的注入过程&#xff0c;写清楚注入步骤&#xff1b; 宽字节概念 1、如果一个字符的大小是一个字节的&#xff0c;称为窄字节&#xff1b; 2、如果一个字符的大小是两个及以上字节的&#xff0c;称为宽字节&#xff1b;像GB2312、GBK、GB1803…