使用jdbc拼接条件查询语句时如何防止sql注入
程序员文章站
2023-02-26 16:12:24
本人微信公众号,欢迎扫码关注! 使用jdbc拼接条件查询语句时如何防止sql注入 最近公司的项目在上线时需要进行安全扫描,但是有几个项目中含有部分老代码,操作数据库时使用的是jdbc,并且竟然好多都是拼接的SQL语句,真是令人抓狂。 在具体改造时,必须使用PreparedStatement来防止SQ ......
本人微信公众号,欢迎扫码关注!
使用jdbc拼接条件查询语句时如何防止sql注入
- 最近公司的项目在上线时需要进行安全扫描,但是有几个项目中含有部分老代码,操作数据库时使用的是jdbc,并且竟然好多都是拼接的sql语句,真是令人抓狂。
-
在具体改造时,必须使用preparedstatement来防止sql注入,普通sql语句比较容易改造,本重点探讨在拼接查询条件的时候如何方式sql注入,具体思路请参考下面的示例代码。
1 数据库示例数据
2 使用statement(不防止sql注入)
2.1 示例代码
@test public void statementtest() { string username = "tom"; string sex = "1"; string address = "' or '1'='1"; statement stat = null; resultset res = null; connection conn = connectionfactory.getconnection(); string sql = "select * from user where 1 = 1"; sql += username == null ? "" : " and username = '" + username + "'"; sql += sex == null ? "" : " and sex = '" + sex + "'"; sql += address == null ? "" : " and address = '" + address + "'"; system.out.println(sql); try { stat = conn.createstatement(); res = stat.executequery(sql); printres(res); } catch (sqlexception e) { e.printstacktrace(); } finally { resourceclose.close(res, stat, conn); } }
2.2 控制台结果
select * from user where 1 = 1 and username = 'tom' and sex = '1' and address = '' or '1'='1' 10 tom 2014-07-10 1 beijing 16 tom 2018-07-31 1 shanghai 22 tom 2019-04-16 2 shanghai 24 tom 2019-06-22 1 guangzhou 25 tom 2019-01-22 2 guangzhou 28 tom 2018-07-31 1 shenzhen
2.3 小结
- 经过上面的示例代码我们可以发现,单纯拼接sql语句是非常危险的,特别容易被sql注入,但是如果使用preparestatement的话,像这种条件查询我们预先并不能确定到底有多少个?(占位符),也就不能使用按照?(占位符)索引去设置参数了,那怎么办呢?
-
别担心,此时我们使用一个小小的技巧,具体参考下面的示例代码
3 使用preparestatement(可以防止sql注入)
3.1 示例代码
@test public void preparestatementtest() { string username = "tom"; string sex = null; string address = "' or '1'='1"; preparedstatement stat = null; resultset res = null; connection conn = connectionfactory.getconnection(); string sql = "select * from user where 1 = 1"; list<object> param = new arraylist<>(); if (username != null) { sql += " and username = ?"; param.add(username); } if (sex != null) { sql += " and sex = ?"; param.add(sex); } if (address != null) { sql += " and address = ?"; param.add(address); } system.out.println(sql); try { stat = conn.preparestatement(sql); for (int i = 0; i < param.size(); i++) { stat.setobject(i+1,param.get(i)); } res = stat.executequery(); printres(res); } catch (sqlexception e) { e.printstacktrace(); } finally { resourceclose.close(res, stat, conn); } }
3.2 控制台结果
select * from user where 1 = 1 and username = ? and address = ?
3.3 小结
- 可以看出,使用preparestatement是可以防止sql注入的。
-
但进行类似条件拼接这种操作时,可以先把参数放入一个集合中,然后遍历集合,同时利用setobject(index,obj)这个方法就可以动态的获取参数的索引了,而且不用关心参数是何种类型。
4 问题总结
- 如今在进行项目开发时已经很少使用原生的jdbc了,大多数都用功能强大的框架去完成,他们帮我们简化了很多操作,如获取数据库连接、封装结果集、sql预编译(可以防止sql注入)
如果实在避免不了使用的话一定要使用可以需编译的preparestatement对象,避免被sql注入带来的风险。
上一篇: C++ : 内联函数和引用变量