就是通过把
SQL
命令插入到
Web
表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL
命令。
具体来说,它是利用现有应用程序,将(恶意的)
SQL命令注入到后台数据库引擎执行的能力,它可以通过在
Web
表单中输入(恶意)
SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行
SQL
语句。
比如先前的很多影视网站泄露
VIP会员密码大多就是通过WEB
表单递交查询字符暴出的,这类表单特别容易受到
SQL
注入式攻击。
String username ="admin";
String password=" 'abc' or 1=1 ";
String sql="select * from users where username= '"+username+"' and password= "+password;
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
上段代码就会欺骗到我们的数据库,因为password这一栏永远为真。
所以就需要用到PreparedStatement预状态通道来防止SQL注入的发生。
PreparedStatement
的
接口扩展了
Statement接口,此语句可以动态地提供参数。
我们首先给出一个预状态通道的示例。
PreparedStatement pstmt = null;
try {
String SQL = "Update Employees SET age = ? WHERE id = ?";
PreparedStatement pps = conn.prepareStatement(SQL);
pps.setInt(1,18);
pps.setString(2,'2021001');
ResultSet resultSet = statement.executeQuery(sql);
}
catch (SQLException e) {
}finally {
pps.close();
}
我们发现sql语句中包含?这个符号。
JDBC中的所有参数都由?符号,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。
预状态通道所提供的setXXX()方法将值绑定到所述参数,其中XXX代表要绑定到输入参数的值的Java数据类型。如果忘记提供值,将收到一个SQLException。
每个参数标记由其顺序位置引用。第一个标记表示位置1,下一个位置2等等。但是该方法与Java数组索引不同,它是从0开始。
下面我们来进行一下Statement和PreparedStatement的对比:
(如果对Statement不熟悉,请参考这篇博文:Statement)
(1)statement属于状态通道,PreparedStatement属于预状态通道
(2)预状态通道会先编译sql语句再去执行,比statement执行效率高
(3)预状态通道支持占位符?,给占位符赋值的时候,位置从1开始
(4)预状态通道可以防止sql注入,原因:预状态通道在处理值的时候以字符串的方式处理