若依数据隔离 ${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可以正确替换

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

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

相关文章

医院不良事件上报系统源码,全套源代码

不良事件上报系统源码&#xff0c;医院安全不良事件管理系统源码&#xff0c;医院不良事件上报源码 技术架构&#xff1a;前后端分离&#xff0c;仓储模式&#xff0c;BS架构&#xff0c;有演示&#xff0c;已在多家医院完美运营。 相关技术&#xff1a;PHPvscodevue2elementl…

QML控件--Container

文章目录一、控件基本信息二、控件说明三、属性成员四、成员函数一、控件基本信息 Import Statement: import QtQuick.Controls 2.14 Since: Qt 5.7 Inherits: Control Inherited By: DialogButtonBox, MenuBar, SwipeView, and TabBar 二、控件说明 Container&#xff08;容…

每日一问-ChapGPT-20230414-中医基础-四诊之问诊

文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20230414-中医基础-四诊之问诊中医中的望闻问切介绍&#xff0c;以及对应的名家问诊的具体细节问诊拓展1. 一问寒热二问汗2. 三问头身四问便3. 五问饮食六问胸4. 七聋八渴俱当辨5. 九问旧病十问因6. 再问服药参机辨当日总结每…

vue3 history模式配置及nginx服务器配置

vue的路由方式有hash模式和history模式&#xff0c;history模式路由看起来有好些&#xff0c;路由路径里没有#号&#xff0c;而hash模式默认是有#号的。 vue3开始默认新建的项目都是history模式&#xff0c;不过history模式打包后想要使用正常访问的话&#xff0c;需要后端服务…

gRPC源码解读 传输层数据处理流程

本篇文章主要介绍gRPC Client传输层的处理流程&#xff0c;如有疑问&#xff0c;欢迎指教。 gRPC版本&#xff1a; 1.54.0-dev gRPC基于http2传输&#xff0c;传输层主要处理http2相关的内容。RFC7540制定了http2协议规范&#xff0c;因此&#xff0c;这部分代码的逻辑绝大部分…

【spring】通过抽象类与ApplicationContext编写扩展性强的业务逻辑

通过抽象类与ApplicationContext编写扩展性强的业务逻辑 一、场景分析 我们以支付业务为例&#xff0c;用户每一次支付都会经历永远不变的几个过程&#xff0c;例如&#xff1a;对于库存和金额的前置校验、支付后扣减库存&#xff0c;修改订单状态等等。整个流程变的是什么呢…

使用国密SSL证书,实现SSL/TLS传输层国密改造

密码是保障网络空间安全可信的核心技术和基础支撑&#xff0c;通过自主可控的国产密码技术保护重要数据的安全&#xff0c;是有效提升我国信息安全保障水平的重要举措。因此&#xff0c;我国高度重视商用密码算法的应用并出台相关政策法规&#xff0c;大力推动国产商用密码算法…

【你听说了吗】GPT-5据说已经学完了世界上现存所有的视频

文章目录前言一、GPT-5会带来什么&#xff1f;二、我们该怎么办&#xff1f;总结前言 最近半年要说最火的产品&#xff0c;无疑是ChatGPT &#xff0c;很多同学都在用 GPT 帮助自己工作&#xff0c;学习&#xff0c;提高效率&#xff01;尤其是 GPT4&#xff0c;性能强 GPT3.5…

电脑自动录屏软件哪个好用 电脑自动录屏怎么设置

录屏是很多工作都需要进行的操作&#xff0c;很多会议、培训课程、PPT等都可能需要通过屏幕录制的方式来进行分享。但是目前市面上的录屏软件很多&#xff0c;想找到使用便捷且高效的软件并不容易。今天就来分享一下电脑自动录屏软件哪个好用&#xff0c;电脑自动录屏怎么设置。…

【计算机组成原理 - 第二章】系统总线(完结)

本章参考王道考研相关课程&#xff1a; 【2019版】6.1.1 总线的概念与分类_哔哩哔哩_bilibili 【2019版】6.1.2 总线的性能指标_哔哩哔哩_bilibili 【2019版】6.2 总线仲裁_哔哩哔哩_bilibili 【2019版】6.3 总线操作和定时_哔哩哔哩_bilibili 【2019版】6.4 总线标准_哔哩哔哩…

css 导航栏效果

目录一、前言二、导航栏实现三、多级导航实现一、前言 在网站上面我们经常能看到一些导航栏&#xff0c;当我们点击对应的导航栏菜单时就会跳转到相应的网页&#xff0c;那么导航栏是如何实现的呢&#xff0c;实现它并不难&#xff0c;主要需要使用到ul标签和其它css样式美化它…

ICPC SWERC 2020 K - Unique Activities(SAM记录子串第一次结束位置 or SAM + hash)

两种做法的效率差异 做法一&#xff1a;SAM记录子串第一次结束位置 做法二&#xff1a;SAM hash 题意&#xff1a; 给定一个字符串&#xff0c;让你找到只出现过一次&#xff0c;且长度最短的子串并输出&#xff0c;如果有多个则输出最先出现的那个。 思路&#xff1a…

Python 进阶指南(编程轻松进阶):十二、使用 Git 组织您的代码项目

原文&#xff1a;http://inventwithpython.com/beyond/chapter12.html 版本控制系统是记录所有源代码变更的工具&#xff0c;使检索旧版本代码变得容易。把这些工具想象成复杂的撤销功能。例如&#xff0c;如果您替换了一个函数&#xff0c;但后来发现您更喜欢旧的函数&#xf…

力扣119杨辉三角 II:代码实现 + 方法总结(数学规律法 记忆法/备忘录)

文章目录第一部分&#xff1a;题目第二部分&#xff1a;解法①-数学规律法2.1 规律分析2.2 代码实现2.3 需要思考第三部分&#xff1a;解法②-记忆法&#xff08;备忘录&#xff09;第四部分&#xff1a;对比总结第一部分&#xff1a;题目 &#x1f3e0; 链接&#xff1a;119.…

低静态电流-汽车电池反向保护系统的方法

低静态电流-汽车电池反向保护系统的方法 背景 车辆中电子电路数量不断增加&#xff0c;使得需要消耗的电池电量也随之大幅增长。为了支持遥控免钥进入和安全等功能&#xff0c;即使在汽车停车或熄火时&#xff0c;电池也要持续供电。 由于所有车辆都使用有限的电池供电&…

第八章 Vite4+Vue3+Vtkjs 完整demo演示

一、介绍 😆 😆 vtk.js是一个基于WebGL的开源3D可视化库,它可以在Web浏览器中呈现高质量的3D图形。vtk.js提供了一个易于使用的API,可以用于创建各种类型的3D可视化,包括科学、医学、工程和地球科学等领域。vtk.js支持多种数据格式,包括VTK、DICOM、STL等,可以轻松地…

刘二大人《Pytorch深度学习实践》第十一讲卷积神经网络(高级篇)

文章目录Inception-v1实现Skip Connect实现Inception-v1实现 Inception-v1中使用了多个11卷积核&#xff0c;其作用&#xff1a; (1)在大小相同的感受野上叠加更多的卷积核&#xff0c;可以让模型学习到更加丰富的特征。传统的卷积层的输入数据只和一种尺寸的卷积核进行运算&am…

工厂模式白话 - 3种都有哦

前言 工厂模式&#xff08;Factory Pattern&#xff09;里所谓的“工厂”和现实生活中的工厂一样 主要作用都是生产产品 像食品厂、服装厂、汽车厂生产吃的、穿的、开的 设计模式里的工厂则是生产对象 划分 工厂模式可分为简单工厂、工厂方法、抽象工厂3种 有啥不同呢&a…

C语言——变参函数

一、定义 一般函数的参数列表是固定的&#xff0c;所以在调用时传入的实参的个数和格式必须和实参匹配&#xff1b;在函数式中&#xff0c;不需要关心实参&#xff0c;直接调用形参即可。 变参函数&#xff0c;就是参数的个数及类型都不确定的函数&#xff0c;常见变参函数如pr…

透过Gartner最新报告,认识“超级边缘”

当下&#xff0c;酝酿能量的超级边缘。最近&#xff0c;我们在谈视频化狂飙、谈AIGC颠覆、谈算力动能不足&#xff0c;很少谈及边缘。但“边缘”恰恰与这一切相关&#xff0c;且越发密不可分&#xff0c;它是未来技术发展的极大影响因子。 “到2025年&#xff0c;超过70%的组织…
最新文章