JDBCSQLPreparedStatement_0">JDBC学习(三)—SQL注入问题/PreparedStatement对象
01 SQL注入问题
所谓SQL注入,就是通过把SQL命令插入到Web表单提交,最终达到欺骗服务器执行恶意的SQL命令。
程序示例:以SQL语句:select * from users where name = ‘不存在的用户名’ or 1=1;为例
public class TestDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写SQL语句
/*
如果输入数据库表单中有的用户名,可以获得正确的结果
如果输入不存在的用户名,查询会失败
如果输入select * from users where name = '不存在的用户名' or 1=1;
*/
System.out.print("请输入你要查询的用户名:");
String username = scanner.nextLine();
String sql = "select * from users where name =" +username;
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(resultSet,statement,connection);
}
}
}
运行结果:
02 PreparedStatement对象
PreperedStatement是Statement的子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得
PreperedStatement可以解决SQL注入问题:PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
/*
preparedStatement的占位符:
preparedStatement.setXXX [xxx:对应占位符数据的类型] (?索引[从1开始] ,传入的值)
示例:
preparedStatement = connection.prepareStatement("select * from users where id = ?and name = ?");
preparedStatement.setInt(1,id);
preparedStatement.setString(1,username);
resultSet = preparedStatement.executeQuery();
*/
程序示例:
public class TestDemo2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.输入SQL语句
System.out.print("请输入你要查询的用户名:");
String username = scanner.nextLine();
//3.获取preparedStatement对象,预编译SQL语句
preparedStatement = connection.prepareStatement("select * from users where name = ?");
preparedStatement.setString(1,username);
//4.执行SQL语句
resultSet = preparedStatement.executeQuery();
//5.获取结果
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6.释放资源
JDBCUtils.closeAll(resultSet,preparedStatement,connection);
}
}
}
运行结果:不能通过SQL注入获取用户名和密码。
03 PreparedStatement和statement的区别
**相同点 : **
都是用来执行sql语句的
不同点 :
Statement 不安全 , 不能预编译SQL , 不能使用占位符 , 容易造成SQL语句拼接错误,不能防止SQL注入攻击
preparedStatement 安全 ,可以防止SQL注入攻击,可以预编译SQL语句 , 可以使用 ?作为占位符 。
Statement 先写SQL语句再执行;
preparedStatement 直接编译SQL , 调用方法执行 ; preparedStatement.execute();