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.mzph.cn/pingmian/66170.shtml

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

相关文章

Java字符编码与正则表达式深度解析

Java字符编码与正则表达式深度解析 1. 字符编码发展 1.1 ASCII 码 在计算机最初发明时&#xff0c;主要用于数值计算&#xff0c;但随着计算需求的增加&#xff0c;人们发现计算机可以用来处理文本信息。因此&#xff0c;将字符映射为数字来表示。 字母 ‘A’ 映射为 65&am…

前端(十)js的使用

js的使用 文章目录 js的使用一、模态框二、使用js控制盒子变色三、图片轮播效果四、图片5s消失 一、模态框 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title><style>* {m…

Docker 远程访问完整配置教程以及核心参数理解

Docker 远程访问完整配置教程 以下是配置 Docker 支持远程访问的完整教程&#xff0c;包括参数说明、配置修改、云服务器安全组设置、主机防火墙配置&#xff0c;以及验证远程访问的详细步骤。 1. 理解 -H fd:// 参数的作用&#xff08;理解了以后容易理解后面的操作&#xff…

第十一章 图论

/* * 题目名称&#xff1a;连通图 * 题目来源&#xff1a;吉林大学复试上机题 * 题目链接&#xff1a;http://t.cn/AiO77VoA * 代码作者&#xff1a;杨泽邦(炉灰) */#include <iostream> #include <cstdio>using namespace std;const int MAXN 1000 10;int fathe…

新服务器Linux网络配置

1、查看网口 ifconfig找到enp3s0或者 ens33&#xff0c;如果有ip&#xff0c;不用配置&#xff0c;本文结束。 2、如果不显示ip,打开文件/etc/sysconfig/network-scripts&#xff08;以enp3s0为例&#xff09; vi /etc/sysconfig/network-scripts/ifcfg-enp3s03、修改 //修…

leetcode hot 100 只出现一次的数字

136. 只出现一次的数字 已解答 简单 相关标签 相关企业 提示 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且…

汇编学习笔记

汇编 1. debug指令 -R命令(register) 查看、改变CPU寄存器的内容 r ax 修改AX中的内容 -D命令(display) 查看内存中的内容 -E命令(enter) 改写内存中的内容 -U命令(unassenble反汇编) 将内存中的机器指令翻译成汇编指令 -T命令(trace跟踪) 执行一条机器指令 -A命令…

Flutter踩坑记-第三方SDK不兼容Gradle 8.0,需适配namespace

最近需要集成Flutter作为Module&#xff0c;Flutter依赖了第三方库&#xff0c;Gradle是8.0版本。 编译报错&#xff1a; 解决办法是在.android根目录下的build.gradle下新增一行代码&#xff1a; buildscript {ext.kotlin_version "1.8.22"repositories {google()…

【Qt】如何保证线程安全(以日志写入为例)

前言 在近日学习中发现&#xff0c;如果开发一个单例模式的日志系统&#xff0c;难免会出现多个线程记录日志的情况&#xff0c;这个时候线程可能导致竞争&#xff0c;或者始料未及的情况发生。 通过学习&#xff0c;如果要保证线程安全&#xff0c;要使用互斥锁QMutex&#xf…

SMMU软件指南之系统架构考虑

安全之安全(security)博客目录导读 目录 5.1 I/O 一致性 5.2 客户端设备 5.2.1 地址大小 5.2.2 缓存 5.3 PCIe 注意事项 5.3.1 点对点通信 5.3.2 No_snoop 5.3.3 ATS 5.4 StreamID 分配 5.5 MSI 本博客介绍与 SMMU 相关的一些系统架构注意事项。 5.1 I/O 一致性 如…

【信息系统项目管理师】【综合知识】【备考知识点】【思维导图】第十一章 项目成本管理

word版☞【信息系统项目管理师】【综合知识】【备考知识点】第十一章 项目成本管理 移动端【思维导图】☞【信息系统项目管理师】【思维导图】第十一章 项目成本管理

九进制转10进制

//第一种 运用循环 public class Main { public static void main(String[] args) { Scanner scan new Scanner(System.in); //在此输入您的代码... int numscan.nextInt(); int result0; int p1; while(num>0) { int nnum%10; resultn*p; numnum/10; pp*9; } System.out.…

计算机毕业设计PyHive+Hadoop深圳共享单车预测系统 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Java集合框架全面解析:从基本集合到线程安全集合

在Java中&#xff0c;集合&#xff08;Collection&#xff09;是用来存储和操作对象的框架&#xff0c;它是Java程序中不可或缺的组件之一。集合框架提供了丰富的数据结构&#xff0c;使数据的存储、查找、插入和删除变得更加高效。在这篇博客中&#xff0c;我们将详细介绍Java…

C++ 复习总结记录二

C 复习总结记录二 主要内容 1、认识面向过程和面向对象 2、类的引入 3、类的定义 4、类的访问限定符及封装 5、类的作用域 6、类的实例化 7、类的对象大小的计算 8、类成员函数的 this 指针 一 认识面向过程和面向对象 C语言是面向过程的&#xff0c;关注的是过程&a…

Mysql运维利器之备份恢复-xtrabackup 安装

1、插件下载 xtrabackup 下载地址 找到自己mysql版本对应得 插件版本下载 2、执行安装命令 yum localinstall percona-xtrabackup-80-8.0.26-18.1.el7.x86_64.rpm 安装完毕&#xff01;查看版本信息 xtrabackup --version 安装完毕&#xff01;&#xff01;&#xff01;

Java枚举和常量类的区别以及优缺点

枚举&#xff08;Enum&#xff09;的深度解析 定义与语法&#xff1a; public enum Color {RED, GREEN, BLUE;private final String hexCode;Color() {// 默认构造函数可以为空&#xff0c;或根据需要初始化。this.hexCode "default";}Color(String hexCode) {thi…

Hoverfly 任意文件读取漏洞(CVE-2024-45388)

漏洞简介 Hoverfly 是一个为开发人员和测试人员提供的轻量级服务虚拟化/API模拟/API模拟工具。其 /api/v2/simulation​ 的 POST 处理程序允许用户从用户指定的文件内容中创建新的模拟视图。然而&#xff0c;这一功能可能被攻击者利用来读取 Hoverfly 服务器上的任意文件。尽管…

深入理解 MVCC 与 BufferPool 缓存机制

深入理解 MVCC 与 BufferPool 缓存机制 在 MySQL 数据库中&#xff0c;MVCC&#xff08;Multi-Version Concurrency Control&#xff09;多版本并发控制机制和 BufferPool 缓存机制是非常重要的概念&#xff0c;它们对于保证数据的一致性、并发性以及提升数据库性能起着关键作用…

Aloudata AIR | 逻辑数据平台的 NoETL 之道

一文为你介绍 Aloudata AIR 逻辑数据平台的技术原理与核心价值 本文主旨是介绍逻辑数据平台的技术原理与核心价值&#xff0c;包含几个部分的内容&#xff1a; 首先&#xff0c;简要阐述逻辑数据平台出现的背景&#xff1b;其次&#xff0c;详细讲解逻辑数据平台的构建方法&am…