PreparedStatement接口是Statement的子接口,它直接继承并重载了Statement的方法。
PreprareStatement预处理对象为什么能预防SQL注入提高安全性呢?
因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库以参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1’也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了!
JDBC用预处理对象操作数据实例:
以delete删除为例
/**
* 预处理对象PreparedStatement
*
* 提高执行速度尤其是多次操作数据库的情况;预防SQL注入
*/
void delete() {
// TODO Auto-generated method stub
String url = "jdbc:mysql://192.168.1.45:3306/employ";
String uerName = "root";
String password = "udd@123";
// 1.注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 2.获得连接对象
conn = DriverManager.getConnection(url, uerName, password);
// 3.预定义SQL语句
String sql = "DELETE FROM emp WHERE emp_no=?";
// 4.获得预处理对象
pstmt = conn.prepareStatement(sql);
// 5.设置参数值
pstmt.setInt(1, 99);
// 6.执行更新SQL
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7.释放资源
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
PreprareStatement对象还支持批量处理addBatch,excuteBatch。
SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统
SQL注入防范:
- 使用参数化的过滤性语句
- 要防御SQL注入,用户的输入就绝对不能直接被嵌入到SQL语句中。
- 输入验证
- 检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行。
- 加密处理
- 将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较——这相当于对用户输入的数据进行了“消毒”处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。
- 存储过程来执行所有的查询
- SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限可以限制到只允许特定的存储过程执行,所有的用户输入必须遵从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。