若依数据隔离 ${params.dataScope} 替换 优化为sql 替换

若依数据隔离 ${params.dataScope} 替换 优化为sql 替换

安全问题:有风险的SQL查询:MyBatis解决

若依框架的数据隔离是通过 ${params.dataScope} 实现的 
但是在代码安全扫描的时候$ 符会提示有风险的SQL查询:MyBatis
所以我们这里需要进行优化

参考:
MyBatis-Plus实现动态表名
MyBatis-Plus实现动态表名只能实现表名替换 也就是除了from 后面的$符号都替换不了
所以我们需要进行改造
在这里插入图片描述

导入依赖

 <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

RequestDataHelper



import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.Map;

public class RequestDataHelper {
    /**
     * 请求参数存取
     */
    private static final ThreadLocal<Map<String, Object>> REQUEST_DATA = new ThreadLocal<>();

    /**
     * 设置请求参数
     *
     * @param requestData 请求参数 MAP 对象
     */
    public static void setRequestData(Map<String, Object> requestData) {
        REQUEST_DATA.set(requestData);
    }

    /**
     * 获取请求参数
     *
     * @param param 请求参数
     * @return 请求参数 MAP 对象
     */
    public static <T> T getRequestData(String param) {
        Map<String, Object> dataMap = getRequestData();
        if (CollectionUtils.isNotEmpty(dataMap)) {
            return (T) dataMap.get(param);
        }
        return null;
    }

    /**
     * 获取请求参数
     *
     * @return 请求参数 MAP 对象
     */
    public static Map<String, Object> getRequestData() {
        return REQUEST_DATA.get();
    }
}

MybatisPlusConfig





import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class MybatisPlusConfig {
    static List<String> tableList(){
        List<String> tables = new ArrayList<>();
        //表名 C55EA8171877E962E08DFF63AA367884123 可以为任意字符  建议复杂度高点 如果重复 会造成替换bug
        tables.add("C55EA8171877E962E08DFF63AA367884123");
        return tables;
    }

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addMyInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // mybatis-plus DynamicTableNameInnerInterceptor 只能实现表名替换 所以这里我们优化了使用我们自己的拦截器LizzMybatisIntercepts
//        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
//        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
//            String newTable = null;
//            for (String table : tableList()) {
//                newTable = RequestDataHelper.getRequestData(table);
//                if (table.equals(tableName) && newTable!=null){
//                    tableName = newTable;
//                    break;
//                }
//            }
//            return tableName;
//        });
 // mybatis-plus DynamicTableNameInnerInterceptor 只能实现表名替换 所以这里我们优化了使用我们自己的拦截器LizzMybatisIntercepts
        LizzMybatisIntercepts lizzMybatisIntercepts = new LizzMybatisIntercepts();
        interceptor.addInnerInterceptor(lizzMybatisIntercepts);
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            sqlSessionFactory.getConfiguration().addInterceptor(interceptor);
        }
    }
}


LizzMybatisIntercepts


import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.sql.SQLException;

@Slf4j
public class LizzMybatisIntercepts implements InnerInterceptor {

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        log.info("#####beforeQuery");
        String sql = boundSql.getSql();
        // 这里是获取到需要替换到的sql 通过 PluginUtils.mpBoundSql(boundSql); 替换   mybatis-plus表名替换源码的原理也是这个
        String params = RequestDataHelper.getRequestData("C55EA8171877E962E08DFF63AA367884123");
        String param = sql.replaceAll("C55EA8171877E962E08DFF63AA367884123", params);
        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        mpBs.sql(param);

    }


}

测试

mapper

    <select id="getList" resultType="com.wys.entity.User">
        SELECT *
	        FROM user where name=#{name} and C55EA8171877E962E08DFF63AA367884123

    </select>

UserController

    @GetMapping("/listUser")
    public List listUser(){

        RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
            put("C55EA8171877E962E08DFF63AA367884123", "1=1");
        }});
       User user=new User();
        user.setName("111111");
        List list = userMapper.getList(user);
    
       return list;

    }

若依代码替换如下

相当于我们手动从实体类拿出来需要替换的sql 然后塞到我们的拦截器里面 有拦截器去替换

 // 若依数据隔离 ${params.dataScope} 替换 优化sql 替换
        String dataScope="";
        Map<String, Object> params = role.getParams();
        if (params!=null && params.size()>0){
          dataScope = params.get("dataScope").toString();

        }
        String finalDataScope = dataScope;
        RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
            put("C55EA8171877E962E08DFF63AA367884123", finalDataScope);

        }});
		

修改前后对比图

在这里插入图片描述

执行sql打印
在这里插入图片描述
可以看到 我们的 sql可以正确替换

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5分钟学会Ribbon负载均衡

文章目录一、Ribbon1.1 Ribbon的负载均衡流程&#xff1a;1.2 负载均衡策略1.2.1 内置的负载均衡策略1.2.2 如何修改负载均衡1.3 加载方式一、Ribbon 1.1 Ribbon的负载均衡流程&#xff1a; 获取可用的服务列表&#xff1a;客户端在进行服务调用之前&#xff0c;首先需要获取可…

如何基于ChatGPT+Avatar搭建24小时无人直播间

0 前言 最近朋友圈以及身边很多朋友都在研究GPT开发&#xff0c;做了各种各样的小工具小Demo&#xff0c;AI工具用起来是真的香&#xff01;在他们的影响下&#xff0c;我也继续捣鼓GPT Demo&#xff0c;希望更多的开发者加入一起多多交流。 上一篇结合即时通 IM SDK捣鼓了一个…

SpringAOP入门基础银行转账实例(进阶版)------------事务处理

SpringAOP入门基础银行转账实例**&#xff08;进阶版&#xff09;**------------事务处理 由上一节讲述的通过Connection和QueryRunner对事务进行的处理(详情可以去我之前写的博客文章&#xff1a;https://blog.csdn.net/m0_56245143/article/details/130069160?spm1001.2014…

VMware vSphere 8.0c - 企业级工作负载平台

ESXi 8.0.0 & vCenter Server 8.0.0 GA (General Availability) 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vsphere-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 2023-03-30, VMware vSphere 8.0c 发…

静态库与动态库

库是已经写好的、成熟的、可复用的代码。在我们的开发的应用中经常有一些公共代码是需要反复使用的&#xff0c;就把这些代码编译为库文件。库可以简单看成一组目标文件的集合&#xff0c;将这些目标文件经过压缩打包之后形成的一个可执行代码的二进制文件。库有两种&#xff1…

Ubuntu硬盘分区、挂载

文章目录1、使用命令查看硬盘情况2、分区3、格式化分区4、挂载手动挂载自动挂载1、使用命令查看硬盘情况 sudo fdisk -l 可以看到这里有个未分区的4T硬盘 如&#xff1a;sdb 这样的是硬盘 sdb1 sdb2 这样的是分区&#xff0c;现在还没分区 2、分区 sudo parted /dev/sdb (s…

一切都是命中注定的!

“光锥之内就是命运”&#xff0c;这是刘慈欣的《三体黑暗森林》里一句话&#xff0c;如果我们看到一件事情正在发生&#xff0c;那么它早在过去无论是几秒前还是几千年前&#xff0c;就已经发生了&#xff0c;我们无法改变这个命运。 孔明叹曰&#xff1a;“谋事在人&#xf…

树莓派通过网线连接笔记本实现笔记本电脑Wifi的网络共享

基于windows电脑连接树莓派进行设置&#xff1a;通过通过一根网线&#xff0c;连接树莓派和电脑&#xff0c;使电脑和树莓派构成一个局域网&#xff0c;然后树莓派接收来自笔记本电脑wifi网络的共享网络。操作方法类似台式机通过网线共享笔记本电脑无线网络的步骤 1、 保证笔记…

总结816

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 高等数学&#xff1a;一元积分&#xff0c;算是彻底过一遍了&#xff0c;但还是需要再回顾一遍。今日一道变限积分求导出…

简单的单目测距实验

一、原理 简单的单目测距方法&#xff0c;假设相机平面和物体平面平行&#xff0c;相机正对着物体表面拍摄&#xff0c;则可以利用相似三角形法。 用相似三角形计算物体或者目标到相机的距离&#xff0c;将使用相似三角形来计算相机到一个已知的物体或者目标的距离。 假设有…

执行数学的运算

数学是计算机编程的重要能力。遗憾的是&#xff0c;对shell脚本来说&#xff0c;这个处理过程比较麻烦。在shell脚本中两种途径来进行数学运算。 expr命令 最开始&#xff0c;Bourne shell提供了一个特别的命令用来处理数学表达式。expr命令允许在命令行上处理数学数学表达式。…

算法学习day59

算法学习day591.力扣503.下一个更大元素II1.1 题目描述1.2 分析1.3代码2.力扣42. 接雨水2.1 题目描述2.2 分析2.3 代码3.参考资料1.力扣503.下一个更大元素II 1.1 题目描述 题目描述&#xff1a; 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&a…

【Java 并发编程】一文了解线程间有哪些通信方式?

一文了解线程间有哪些通信方式&#xff1f;1. synchronized 内置锁2. volatile 关键字3. 等待/通知机制3.1 等待wait()wait(long)wait(long, int)等待方需遵循如下原则3.2 通知notify()notifyAll()通知方需遵循如下原则notify() 和 notifyAll() 应该用谁&#xff1f;4. 管道输入…

BusterNet网络Python模型实现学习笔记一

实在是无力吐槽了&#xff0c;心力交瘁。作者Github仓库给了错误的 USCISI-CMFD-Small 数据集。自己捣鼓了半天&#xff0c;发现原来是压缩之后数据集&#xff0c;也就是 LMDB 文件格式出错了。实在是误人子弟&#xff0c;自己已经气急败坏了现在… 但是既然论文都花那么长时间…

数据分析之Pandas 基础入门

一、初始Pandas pandas 是数据分析三大件之一&#xff0c;是Python的核心分析库&#xff0c;它提供了快捷、灵活、明确的数据结构&#xff0c;它能够简单、直观、快速的处理各种类型的数据结构。 pandas 支持的数据结构如下&#xff1a; SQL 或Excel 类似的数据有序或无序的…

【学习笔记】unity脚本学习(三)(向量 Vector3)

目录向量复习高中向量基础【数学】向量的四则运算、点积、叉积、正交基叉乘公式叉乘运算定理向量、坐标系点积叉积Vector3 三维向量静态变量变量变量normalized 与 Normalize() 方法静态方法ClampMagnitudeCrossDistanceDotMoveTowards其他变换类似Lerp 在两个点之间进行线性插…

实现一个简单但有趣的AR效果(Web)

有人说:一个人从1岁活到80岁很平凡,但如果从80岁倒着活,那么一半以上的人都可能不凡。 生活没有捷径,我们踩过的坑都成为了生活的经验,这些经验越早知道,你要走的弯路就会越少。

MySQL 库操作

目录 创建数据库 语法 案例 字符集和校验规则&#xff08;建数据库/建表用&#xff09; 查看系统默认字符集以及校验规则 db.opt 更改 查看数据库支持的字符集 查看数据库支持的字符集校验规则 校验规则对数据库的影响 排升序 操纵数据库 查看数据库 显示创建语…

洛谷P2822:组合数问题 ←(帕斯卡法则+取模+前缀和)

【题目来源】https://www.luogu.com.cn/problem/P2822https://www.acwing.com/problem/content/525/【题目描述】 组合数​表示的是从n个物品中选出m个物品的方案数。举个例子&#xff1a;从(1,2,3)三个物品中选择两个物品可以有(1,2)&#xff0c;(1,3)&#xff0c;(2,3) 这三种…

MySQl_1

一.相关概念 数据库&#xff1a;存放数据的仓库 数据库管理系统&#xff1a;操作和管理数据库的大型软件&#xff0c;如mysql SQL&#xff1a;一种操作 关系型数据库管理系统的语言&#xff0c;定义了一套操作关系型数据库管理系统的统一标准。 关系型数据库&#xff1a;有多…