本人微信公众号,欢迎扫码关注!
使用jdbc拼接条件查询语句时如何防止sql注入
- 最近公司的项目在上线时需要进行安全扫描,但是有几个项目中含有部分老代码,操作数据库时使用的是jdbc,并且竟然好多都是拼接的SQL语句,真是令人抓狂。
- 在具体改造时,必须使用PreparedStatement来防止SQL注入,普通SQL语句比较容易改造,本重点探讨在拼接查询条件的时候如何方式SQL注入,具体思路请参考下面的示例代码。
1 数据库示例数据
2 使用statement(不防止SQL注入)
2.1 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27@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 控制台结果
1 | SELECT * FROM user WHERE 1 = 1 AND username = 'tom' AND sex = '1' AND address = '' or '1'='1' |
2.3 小结
- 经过上面的示例代码我们可以发现,单纯拼接SQL语句是非常危险的,特别容易被SQL注入,但是如果使用prepareStatement的话,像这种条件查询我们预先并不能确定到底有多少个?(占位符),也就不能使用按照?(占位符)索引去设置参数了,那怎么办呢?
- 别担心,此时我们使用一个小小的技巧,具体参考下面的示例代码
3 使用prepareStatement(可以防止SQL注入)
3.1 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40@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 控制台结果
1 | SELECT * FROM user WHERE 1 = 1 AND username = ? AND address = ? |