找到sql里面参数字段占位符的位置,方便对字段进行加密存储

CCJSqlParserUtil工具是强大,难用也是真的,得分析sql的各种各样的表达式。从中递归找出业务需要的。

public class SqlExpressionAnalyzer {


    public static void main(String[] args) {
        String sql = "select id,user_name from sys_user t1,sys_office t2 where t1.id=t2.id and mobile =? and user_name like '%abc%' and user_name like ? and user_name like ?  and position=? and bbb in ('1','2') and ccc in (?,?) and sex='1' and (photo='abc' or headImg='abc' or user_name like '%abc%')  and nation='2'" +
                " and id in (select id from relation_user where acc=?) and user_name in (select user_name from table_3 where user_name in (?,?,?,?,?) and user_name in ('1','3','4')) " +
                "and mobile =(case when is_using=1 then '1' when is_using=0 then '2' else '3' end)";

        String updateSql = "update sys_user set mobile=?,user_name='张三' where mobile='1' and id='1'";

        String insertSql = "insert into sys_user (id,mobile,user_name) values (?,?,?)";

        String delSql = "delete from sys_user where mobile=? and user_name=? and mobile in (?,?,?,?,?) and user_name in ('李四','张三')";
        AnalyzerResult analyzerResult = parse(delSql);
        System.out.println(analyzerResult);
    }

    public static AnalyzerResult parse(BoundSql boundSql) {
        return null != boundSql ? parse(boundSql.getSql()) : AnalyzerResult.empty();
    }

    public static AnalyzerResult parse(String sql) {
        Statement statement;
        try {
            statement = CCJSqlParserUtil.parse(sql);
        } catch (JSQLParserException e) {
            throw new LocalException(e.getMessage());
        }
        if (statement instanceof Select) {
            return analyzeSelect((Select) statement);
        } else if (statement instanceof Update) {
            return analyzeUpdate((Update) statement);
        } else if (statement instanceof Insert) {
            return analyzerInsert((Insert) statement);
        } else if (statement instanceof Delete) {
            return analyzerDelete((Delete) statement);
        }
        return AnalyzerResult.empty();

    }

    private static AnalyzerResult analyzerInsert(Insert insert) {
        AnalyzerResult analyzerResult = new AnalyzerResult(insert.getTable());
        List<Column> columns = insert.getColumns();
        List<Expression> setExpressionList = insert.getSetExpressionList();
        if (null != setExpressionList && setExpressionList.size() == columns.size()) {
            analyzerResult.putResults(columns, setExpressionList);
        } else {
            ItemsList itemsList = insert.getItemsList();
            if (itemsList instanceof ExpressionList) {
                ExpressionList expressionList = (ExpressionList) itemsList;
                List<Expression> expressions = expressionList.getExpressions();
                analyzerResult.putResults(columns, expressions);
            } else if (itemsList instanceof MultiExpressionList) {
                MultiExpressionList multiExpressionList = (MultiExpressionList) itemsList;
                List<ExpressionList> exprList = multiExpressionList.getExprList();
                for (ExpressionList expressionList : exprList) {
                    List<Expression> expressions = expressionList.getExpressions();
                    analyzerResult.putResults(columns, expressions);
                }
            }
        }
        return analyzerResult;
    }

    private static AnalyzerResult analyzerDelete(Delete delete) {
        AnalyzerResult result = new AnalyzerResult(delete.getTable());
        Expression where = delete.getWhere();
        analyzeWhere(where, result);
        if (result.isExitReplaceStr()) {
            result.setReplaceSql(delete.toString());
        }
        return result;
    }

    private static AnalyzerResult analyzeUpdate(Update update) {
        List<Table> tables = update.getTables();
        if (tables.isEmpty()) {
            return AnalyzerResult.empty();
        }
        AnalyzerResult result = new AnalyzerResult(tables.get(FIRST));

        List<Column> columns = update.getColumns();
        List<Expression> expressions = update.getExpressions();
        result.putResults(columns, expressions);

        Expression where = update.getWhere();
        analyzeWhere(where, result);
        if (result.isExitReplaceStr()) {
            result.setReplaceSql(update.toString());
        }
        return result;
    }

    private static AnalyzerResult analyzeSelect(Select select) {
        PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
        // 分析表达式
        AnalyzerResult result = new AnalyzerResult((Table) plainSelect.getFromItem());

        analyzeWhere(plainSelect.getWhere(), result);
        // 替换sql
        if (result.isExitReplaceStr()) {
            result.setReplaceSql(plainSelect.toString());
        }
        return result;
    }

    private static void analyzeWhere(Expression expression, AnalyzerResult result) {
        if (null == expression) {
            return;
        }
        // 正常xxx xxx xxx
        if (expression instanceof BinaryExpression) {
            BinaryExpression binaryExpression = (BinaryExpression) expression;
            Expression leftExpression = binaryExpression.getLeftExpression();
            Expression rightExpression = binaryExpression.getRightExpression();

            boolean isColumn = leftExpression instanceof Column;
            boolean isString = rightExpression instanceof StringValue;
            boolean isJdbc = rightExpression instanceof JdbcParameter;
            boolean isValue = isString || isJdbc;
            if (isColumn && isValue) {
                Column column = (Column) leftExpression;
                boolean isLike = expression instanceof LikeExpression;
                result.putResult(column, rightExpression, isLike);
            } else {
                analyzeWhere(leftExpression, result);
                analyzeWhere(rightExpression, result);
            }
        // in查询
        } else if (expression instanceof InExpression) {
            InExpression binaryExpression = (InExpression) expression;
            Expression leftExpression = binaryExpression.getLeftExpression();
            ItemsList rightItemsList = binaryExpression.getRightItemsList();
            ItemsList leftItemsList = binaryExpression.getLeftItemsList();
            if (leftExpression instanceof Column) {
                Column column = (Column) leftExpression;
                boolean isInValue = false;
                ExpressionList expressionList = null;
                if (rightItemsList instanceof ExpressionList) {
                    isInValue = true;
                    expressionList = (ExpressionList) rightItemsList;
                } else if (leftItemsList instanceof ExpressionList) {
                    isInValue = true;
                    expressionList = (ExpressionList) leftItemsList;
                }
                if (isInValue) {
                    result.putResults(column, expressionList.getExpressions());
                } else {
                    if (rightItemsList instanceof Expression) {
                        analyzeWhere((Expression) rightItemsList, result);
                    }
                    if (leftItemsList instanceof Expression) {
                        analyzeWhere((Expression) leftItemsList, result);
                    }
                }
            }
        // 子语句
        } else if (expression instanceof Parenthesis) {
            Parenthesis parenthesis = (Parenthesis) expression;
            Expression parenthesisExpression = parenthesis.getExpression();
            analyzeWhere(parenthesisExpression, result);
        // 子查询
        } else if (expression instanceof SubSelect) {
            SubSelect subSelect = (SubSelect) expression;
            PlainSelect selectBody = (PlainSelect) subSelect.getSelectBody();
            Expression where = selectBody.getWhere();
            analyzeWhere(where, result);
        // case when里面的when条件
        } else if (expression instanceof CaseExpression) {
            CaseExpression caseExpression = (CaseExpression) expression;
            List<WhenClause> whenClauses = caseExpression.getWhenClauses();
            if (ZYListUtils.isNotEmptyList(whenClauses)) {
                for (WhenClause whenClause : whenClauses) {
                    Expression whenExpression = whenClause.getWhenExpression();
                    analyzeWhere(whenExpression, result);
                }
            }
        } else {
            log.warn("not handle expression" + expression.getClass());
        }
    }

}
@Data
public class AnalyzerResult {

    private boolean exitReplaceStr = false;

    private String replaceSql;

    private String tableName;

    private List<ColumnInfo> jdbcColumnInfos = new ArrayList<>();

    private List<ColumnInfo> signJdbcColumnInfos = new ArrayList<>();

    public AnalyzerResult(Table table) {
        this.tableName = table.getName();
    }

    public AnalyzerResult() {
    }

    public Set<Integer> getCryptIndexs() {
        Set<Integer> cryptIndexs = new HashSet<>();
        for (ColumnInfo jdbcColumnInfo : jdbcColumnInfos) {
            cryptIndexs.add(jdbcColumnInfo.getJdbcIndex());
        }
        return cryptIndexs;
    }

    public void putResults(Column column, List<Expression> expressions) {
        if (null != expressions) {
            for (Expression expression : expressions) {
                putResult(column, expression, false);
            }
        }
    }

    public void putResults(List<Column> columns, List<Expression> expressions) {
        if (ZYListUtils.isSingletonList(columns) || ZYListUtils.isEmptyList(expressions)) {
            return;
        }
        for (int i = 0; i < columns.size(); i++) {
            Column column = columns.get(i);
            Expression expression = expressions.get(i);
            this.putResult(column, expression);
        }
    }

    public void putResult(Column column, Expression expression) {
        putResult(column, expression, false);
    }

    public void putResult(Column column, Expression expression, boolean isLike) {
        if (SecurityColumnProviders.matchSecret(this.tableName, column)) {
            if (expression instanceof JdbcParameter) {
                JdbcParameter jdbcParameter = (JdbcParameter) expression;
                this.jdbcColumnInfos.add(new ColumnInfo(column, jdbcParameter));
            } else if (expression instanceof StringValue) {
                this.setExitReplace();
                toReplaceString((StringValue) expression, isLike);
            }
        }

        if (SecurityColumnProviders.matchSign(this.tableName, column)) {
            if (expression instanceof JdbcParameter) {
                JdbcParameter jdbcParameter = (JdbcParameter) expression;
                this.signJdbcColumnInfos.add(new ColumnInfo(column, jdbcParameter));
            }
        }

    }

    private void toReplaceString(StringValue rightExpression, boolean isLike) {
        String value = rightExpression.getValue();
        if (ZYStrUtils.isNull(value)) {
            return;
        }
        SecretProviders secretProviders = ZYSpringUtils.getBean(SecretProviders.class);
        if (null == secretProviders) {
            throw new LocalException("secretProviders is null");
        }
        if (isLike && value.startsWith("%") && value.endsWith("%")) {
            String valueItem = value.substring(1, value.length() - 2);
            String encryptValue = secretProviders.encrypt(valueItem);
            rightExpression.setValue("%" + encryptValue + "%");
        } else {
            rightExpression.setValue(secretProviders.encrypt(value));
        }
    }


    private void setExitReplace() {
        this.exitReplaceStr = true;
    }

    public static AnalyzerResult empty() {
        return new AnalyzerResult();
    }
}

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

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

相关文章

Spring GateWay自定义断言工厂

文章目录 概要整体架构流程最终的处理效果小结 概要 我们在线上系统部署了&#xff0c;灰度环境和生产环境时&#xff0c;可以通过自定义断言工厂去将请求需要路由到灰度环境的用户调用灰度的的服务集群&#xff0c;将正常的用户调用正常集群。 这样&#xff0c;我们可以在上线…

R语言论文插图模板第7期—分组散点图

在之前的文章中&#xff0c;分享过R语言折线图的绘制模板&#xff1a; 柱状图的绘制模板&#xff1a; 本期再来分享一下散点图&#xff08;分组&#xff09;的绘制方法。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;…

碰撞检测 | 基于ROS Rviz插件的多边形碰撞检测仿真平台

目录 0 专栏介绍1 基于多边形的碰撞检测2 碰撞检测仿真平台搭建2.1 多边形实例2.2 外部服务接口2.3 Rviz插件化 3 案例演示3.1 功能介绍3.2 绘制多边形 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及更高阶的运动规划算法轨迹优化实战…

【附源码】Python :PYQT界面点击按钮随机变色

系列文章目录 Python 界面学习&#xff1a;PYQT界面点击按钮随机变色 文章目录 系列文章目录一、项目需求二、源代码三、代码分析3.1 导入模块&#xff1a;3.2 定义App类&#xff1a;3.3 构造函数&#xff1a;3.4 初始化用户界面&#xff1a;3.5 设置窗口属性&#xff1a;3.6 …

基于距离度量学习的异常检测:一种通过相关距离度量的异常检测方法

异常通常被定义为数据集中与大多数其他项目非常不同的项目。或者说任何与所有其他记录(或几乎所有其他记录)显著不同的记录,并且与其他记录的差异程度超出正常范围,都可以合理地被认为是异常。 例如上图显示的数据集中,我们有四个簇(A、B、C和D)和三个位于这些簇之外的点:P1、P…

client网络模块的开发和client与server端的部分联动调试

客户端网络模块的开发 我们需要先了解socket通信的流程 socket通信 server端的流程 client端的流程 对于closesocket()函数来说 closesocket()是用来关闭套接字的,将套接字的描述符从内存清除,并不是删除了那个套接字,只是切断了联系,所以我们如果重复调用,不closesocket()…

Agentic Security:一款针对LLM模型的模糊测试与安全检测工具

关于Agentic Security Agentic Security是一款针对LLM模型的模糊测试与安全检测工具&#xff0c;该工具可以帮助广大研究人员针对任意LLM执行全面的安全分析与测试。 请注意 Agentic Security 是作为安全扫描工具设计的&#xff0c;而不是万无一失的解决方案。它无法保证完全防…

C++(11)类语法分析(2)

C(10)之类语法分析(2) Author: Once Day Date: 2024年8月17日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 源码分析_Once-Day的博客-CSDN博客 …

Python数据结构:集合详解(创建、集合操作)④

文章目录 1. Python集合概述2. 创建集合2.1 使用花括号 {} 创建集合2.2 使用 set() 函数创建集合2.3 创建空集合 3. 集合操作3.1 添加和删除元素3.2 集合的基本操作3.3 集合的比较操作3.4 不可变集合&#xff08;frozenset&#xff09; 4. 综合例子&#xff1a;图书管理系统 Py…

30秒内批量删除git本地分支

在开发过程中&#xff0c;我们经常需要对本地的 Git 分支进行管理。有时&#xff0c;由于各种原因&#xff0c;我们可能需要批量删除本地的分支。这可能是因为某些分支已经不再需要&#xff0c;或者是为了清理本地的分支列表&#xff0c;以保持整洁和易于管理。 要批量删除本地…

没有用的小技巧之---接入网线,有内网没有外网,但是可以登录微信

打开控制面板&#xff0c;找到网络和Internet 选择Internet选项 点击连接&#xff0c;选择局域网设置 取消勾选代理服务器

开放式耳机会打扰到别人吗?四款漏音处理做的好的蓝牙耳机

一般情况下&#xff0c;开放式耳机不会打扰到别人。 开放式耳机通常采用全开放设计&#xff0c;声音不会完全封闭在耳朵里&#xff0c;而是向四周扩散&#xff0c;相比封闭式耳机&#xff0c;其对外界环境的噪音影响更小 。而且现在的开放式耳机在技术上已经有了很大的进步&am…

[数据集][目标检测]工程机械车辆检测数据集VOC+YOLO格式3189张10类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3189 标注数量(xml文件个数)&#xff1a;3189 标注数量(txt文件个数)&#xff1a;3189 标注…

springboot的自动配置和怎么做自动配置

目录 一、Condition 1、Condition的具体实现 2、Condition小结 &#xff08;1&#xff09;自定义条件 &#xff08;2&#xff09;SpringBoot 提供的常用条件注解 二、Enable注解 三、EnableAutoConfiguration 注解和自动配置 1、EnableAutoConfiguration的三个注解属性…

git 学习--GitHub Gitee码云 GitLab

1 集中式和分布式的区别 1.1 集中式 集中式VCS必须有一台电脑作为服务器&#xff0c;每台电脑都把代码提交到服务器上&#xff0c;再从服务器下载代码。如果网络出现问题或服务器宕机&#xff0c;系统就不能使用了。 1.2 分布式 分布式VCS没有中央服务器&#xff0c;每台电脑…

Python编码系列—Python SQL与NoSQL数据库交互:深入探索与实战应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

预警先行,弯道哨兵让行车更安全

预警先行&#xff0c;弯道哨兵让行车更安全”这句话深刻体现了现代交通安全理念中预防为主、科技赋能的重要性。在道路交通中&#xff0c;尤其是复杂多变的弯道区域&#xff0c;交通事故的发生率往往较高&#xff0c;因此&#xff0c;采取有效的预警措施和引入先进的交通辅助设…

怎么管控终端电脑上的移动端口

管控终端电脑上的移动端口&#xff0c;尤其是USB等移动端口&#xff0c;是确保企业数据安全和提升网络管理效率的重要手段。 一、使用注册表编辑器禁用USB端口&#xff08;适用于Windows系统&#xff09; 打开注册表编辑器&#xff1a; 同时按下“WinR”组合键&#xff0c;打…

SEO优化:如何优化自己的文章,解决搜索引擎不收录的问题

可以使用bing的URL检查&#xff0c;来检查自己的文章是不是负荷收录准测&#xff0c;如果页面有严重的错误&#xff0c;搜索引擎是不会进行收录的&#xff0c;而且还会判定文章为低质量文章&#xff01; 检查是否有问题。下面的页面就是有问题&#xff0c;当然如果是误报你也可…

Java并发类API——CompletionService

CompletionService 是 Java 中 java.util.concurrent 包的一部分&#xff0c;用于管理并发任务的执行&#xff0c;并以完成的顺序提供结果。它结合了线程池和阻塞队列的功能&#xff0c;用于提交任务并按照任务完成的顺序来检索结果&#xff0c;而不是按照任务提交的顺序。 接…