Mybatis动态指定表名、列名,如何防止SQL注入?

您所在的位置:网站首页 参数sql注入 Mybatis动态指定表名、列名,如何防止SQL注入?

Mybatis动态指定表名、列名,如何防止SQL注入?

2024-07-13 16:55| 来源: 网络整理| 查看: 265

以下的代码,操作的是MySQL数据库

方式一

因为表名无法通过 CONCAT() 函数进行拼接,所以只能通过 ${} 直接将表名的字符串替换。

SELECT * FROM ${tableName} WHERE deptno = #{deptno}

但是会存在SQL的注入,比如:tableName = dept_01; delete from dept_01; 就会删除所有的数据。

解决方式:通过代码去判断传入的参数是否包含 delete、drop... 等危险操作。

方式二

假设存在数据库中存在 dept_01,dept_02,dept_03..... 这样命名的表,那么怎么做呢?

可以通过存储过程去解决动态指定表名的问题。

1)创建存储过程

DROP PROCEDURE IF EXISTS getName; -- 如果一创建存储过程则删除 DELIMITER $$ -- 定义结束字符,可以任意 -- 创建名称为getName的存储过程,需要传入的参数:tableName表名,deptno条件 CREATE PROCEDURE getName(IN tableName VARCHAR(100), IN deptno INT) BEGIN DECLARE tn VARCHAR(10); -- 创建变量保存表名 set tn = ( -- 查询MySQL中所有的表,然后根据 表所在的数据库 和 表的后缀名称 获取到对应的表名 select table_name from information_schema.TABLES where table_schema='db03' AND table_name LIKE CONCAT('dept_', '%') AND table_name LIKE CONCAT('%', tableName) ); -- 再拼接查询语句 set @sqlStr = CONCAT("SELECT * FROM ", tn," WHERE deptno = '", deptno, "'"); PREPARE sqlStr FROM @sqlStr; EXECUTE sqlStr; -- 执行 END $$ -- 传入参数:表名的后缀 部门id CALL getName('02', 5); -- 测试

测试结果,这样就不存在注入问题,因为表名被作为了条件。

2)接口编写

// Controller层 @GetMapping("selectUnionALL/db03") @ResponseBody public List selectUnionALL() { Dept dept = new Dept(); dept.setDeptno(5L); dept.setTableName("02"); return deptService.selectUnionALL(dept); } // service层 public List selectUnionALL(Dept dept) { return deptMapper.selectUnionALL(dept); } // mapper层 List selectUnionALL(Dept dept);

3)mapper.xml 调用

CALL getName(#{tableName}, #{deptno});

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3