狭义的 SQL注入
称之为狭义,是指我在深入了解前自己对SQL注入的理解,也就是在练习JDBC操作数据库时接触到的SQL注入。
1.1 JDBC
先介绍一下JDBC的概念:JDBC是sun公司(已被Oracle收购)制定一系列接口标准,由不同数据库厂商(Oracle、MySQL等)实现接口方法并封装成驱动文件,供开发人员操作数据库。也就是说,开发人员可采用统一的代码来操作不同的数据库,而无需关注驱动文件的内部实现。
通俗的理解就是JDBC是规范、是接口,不同的数据库厂商要据此编写各自的操作实现。
1.2 SQL注入
我们知道,dao层(负责操作数据库)中执行的SQL语句是拼接出来的,其中有一部分数据是由用户从客户端传入,所以当用户传入的数据中包含SQL关键字时,就有可能通过这些关键字改变SQL语句的语义,从而执行一些特殊的操作,这样的攻击方式就叫做SQL注入攻击。
例如以下用户登录的代码:
public boolean login(String username, String password){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
if (username == null || password == null){
return false;
}
try {
conn = JDBCUtils.getConnection(); //获取数据库链接对象
String sql = "select * from user where username = '" + username + "'and password = '" + password +"'" ;
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(rs,stmt,conn); //释放资源
}
return false;
}程序的逻辑为
- 用户输入用户名和密码
- 在数据库中查找匹配的用户名和密码,若有匹配的则登录成功,否则,提示"用户名或密码错误!"。实际就是在数据库中执行以下sql语句
1. String sql = “select * from user where username = '” + username + “'and password = '” + password +"’" ;上边代码的逻辑看似没有问题,实则问题很大:
当用户这样输入:一个数据库中不存在的用户名,例如bbb,然后输入密码:a' or 'a' = 'a,这样输入竟然也能登陆成功。
原因:
当用户输入以上用户名和密码时,程序就会在数据库中执行以下sql语句
sql :select * from user where username = 'bbb' and password = 'a' or 'a' = 'a' ;
这是一条恒等式,数据库会返回user表中所有的内容,这样rs.next()就会等于true,所以可以登陆成功。
1.3 SQL注入的预防
使用PreparedStatement代替Statement可以有效防止SQL注入的发生。
PreparedStatement利用预编译的机制将sql语句的主干和参数分别传输给数据库服务器,从而使数据库分辨的出哪些是sql语句的主干哪些是参数,这样一来即使参数中带了sql的关键字,数据库服务器也仅仅将他当作参数值使用,关键字不会起作用,从而从原理上防止了sql注入的问题。
例如,上面那条SQl语句就要改成:
String sql = "select * from user where username = ? and password = ?" ;再去给每个 ?占位符赋值
ps.setString(1, name);
ps.setInt(2, password);PreparedStatement主要有如下的三个优点:
- 可以防止sql注入
- 由于使用了预编译机制,执行的效率要高于Statement
- sql语句使用?形式替代参数,然后再用方法设置?的值,比起拼接字符串,代码更加优雅.
PreparedStatement 与Statment比较:
- 语法不同:PreparedStatement可以使用预编译的sql,而Statment只能使用静态的sql
- 效率不同: PreparedStatement可以使用sql缓存区,效率比Statment高
- 安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。
















