本人微信公众号,欢迎扫码关注!

使用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注入带来的风险。

使用jdbc拼接条件查询语句时如何防止sql注入的更多相关文章

  1. sql查询语句时怎么把几个字段拼接成一个字段

    sql查询语句时怎么把几个字段拼接成一个字段SELECT CAST(COLUMN1 AS VARCHAR(10)) + '-' + CAST(COLUMN2 AS VARCHAR(10) ...) a ...

  2. MySQL数据库详解(一)执行SQL查询语句时,其底层到底经历了什么?

    一条SQL查询语句是如何执行的? 前言 ​ 大家好,我是WZY,今天我们学习下MySQL的基础框架,看一件事千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于MyS ...

  3. JAVA jdbc(数据库连接池)学习笔记(二) SQL注入

    PS:今天偶然间发现了SQL的注入...所以就简单的脑补了一下,都是一些简单的例子...这篇写的不怎么样...由于自己没有进行很深的研究... 学习内容: 1.SQL注入的概念...   所谓SQL注 ...

  4. Mybatis 的分页条件查询语句编写

    刚来到一家新公司, 翻看项目代码, 发现一位同事写的查询逻辑很好, 不用插件, 一个语句完成了分页条件查询. 而我之前一般都是在业务层对参数进行判断, 如果有条件,就调用条件查询的方法, 如果没有条件 ...

  5. 当执行一条查询语句时,MySQL内部经历了什么?

    假如说我们有一张表 T ,表里只有一个字段 ID,当我们执行下边这条SQL语句时: mysql> select * fron T where ID=10; 在我们眼中能看到的只是输入一条 SQL ...

  6. 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?

    先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...

  7. MySQL多表查询,Navicat使用,pymysql模块,sql注入问题

    一.多表查询 #建表 create table dep( id int, name varchar(20) ); create table emp( id int primary key auto_i ...

  8. 一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入

    一.JDBC的概述###<1>概念 JDBC:java database connection ,java数据库连接技术 是java内部提供的一套操作数据库的接口(面向接口编程),实现对数 ...

  9. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...

随机推荐

  1. go语言时间比较

    local, _ := time.LoadLocation("Local") starttime, _ := time.ParseInLocation("2006-01- ...

  2. 拾人牙慧篇之——linux文件挂载,基于nfs的文件共享系统安装配置

    一.写在前面 最近需要把阿里云上的四台服务器的项目迁移到客户提供的新的项目中,阿里云的项目平时开发启动的时候知道有个nfs文件系统,表现就是后台管理系统通过freemarker生成的HTML文件,自动 ...

  3. 在Java中谈尾递归--尾递归和垃圾回收的比较(转载)

    我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...

  4. node传统读取文件和promise,async await,

    先上传统文件加载方式代码,传统方式在处理多层嵌套时代码比较混乱 const fs = require('fs') //引入文件系统 function readFile (cb) { fs.readFi ...

  5. 洛谷 P1057 解题报告

    P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...

  6. 学习Layui 第一天

    Layui 官网说这是款经典模块化前端框架 个人觉得Layui很好用,容易上手. 在学习Layui的之前.先去官网下载必要的文件 将这些文件放入项目当中 然后可以到官网看一下示例. 可以做一个简单的表 ...

  7. Global一点小经验

    Global: Global.asax 文件,有时候叫做 ASP.NET 应用程序文件,提供了一种在一个中心位置响应应用程序级或模块级事件的方法,他位于应用程序根目录下. 这个 Global.asax ...

  8. springboot+mybatis+ehcache实现缓存数据

    一.springboot缓存简介 在 Spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓 ...

  9. onConfigurationChanged方法的使用

    在日常生活中,手机会有很多种配置放生改变的情况,当然,有些时候需要监听他们并对他们进行处理,这就涉及到了onConfiguration方法的使用,我大致说一下,这个方法需要发生在屏幕切换横竖屏,或者选 ...

  10. 深入理解HashMap上篇

    前言: HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型.随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化, ...