Mybatis动态指定表名、列名,如何防止SQL注入? |
您所在的位置:网站首页 › 参数sql注入 › Mybatis动态指定表名、列名,如何防止SQL注入? |
以下的代码,操作的是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 |