PreparedStatement * 它是Statement接口的子接口; * 强大之处: - 防SQL攻击; - 提高代码的可读性、可维护性; - 提高效率! * 学习PreparedStatement的用法: - 给出SQL模板! - 调用Connection的PreparedStatement prepareStatement(String sql模板),得到PreparedStatement对象pstmt; - 调用pstmt的setXxx()系列方法sql模板中的?赋值!如:pstmt.setString(1,"zhangsan"); - 调用pstmt的executeUpdate()或executeQuery(),但它的方法都没有参数。 * 预处理的原理 - 服务器的工作: 校验sql语句的语法! 编译:一个与函数相似的东西! 执行:调用函数, - PreparedStatement: 前提:连接的数据库必须支持预处理!几乎没有不支持的! 每个pstmt都与一个sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译。 执行时只是把参数传递过去而已! 若二次执行时,就不用再次校验语法,也不用再次编译!直接执行! 目录 1、什么是SQL攻击 2、演示SQL攻击 3、防止SQL攻击 4、PreparedStatement是什么? 5、PreparedStatement的使用 -------------------------------------------------------------------- 1、什么是SQL攻击 在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句! 例如用户在登录时输入的用户名和密码都是为SQL语句的片段! 2、演示SQL攻击 首先我们需要创建一张用户表,用来存储用户的信息。 CREATE TABLE user( uid CHAR(32) PRIMARY KEY, username VARCHAR(30) UNIQUE KEY NOT NULL, PASSWORD VARCHAR(30) ); INSERT INTO user VALUES('U_1001', 'zs', 'zs'); SELECT * FROM user; 现在用户表中只有一行记录,就是zs。 下面我们写一个login()方法! public boolean login(String username, String password) throws Exception { /* * 一、得到Connection * 二、得到Statement * 三、得到ResultSet * 四、rs.next()返回的是什么,我们就返回什么 */ // 准备四大参数 String driverClassName = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/mydb3"; String mysqlUsername = "root"; String mysqlPassword = "123"; // 加载驱动类 Class.forName(driverClassName); // 得到Connection Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword); // 得到Statement Statement stmt = con.createStatement(); // 给出sql语句,该sql受到攻击后,查询结果与事实不符 String sql="select * from t_user where username='" + username + "' and password='" + password + "'"; //得到ResultSet, ResultSet rs = stmt.executeQuery(sql); //返回boolean类型的:结果集是否有第一行数据。只要表里有数据,就返回true,就能登录,严重问题。 return rs.next(); } SQL注入测试 @Test public void fun1() throws Exception { String username = "a' or 'a'='a"; String password = "a' or 'a'='a"; boolean bool = login(username, password); System.out.println(bool); } 这行当前会使我们登录成功!因为是输入的用户名和密码是SQL语句片段,最终与我们的login()方法中的SQL语句组合在一起! 我们来看看组合在一起的SQL语句: select * from t_user where username='a' or 'a'='a' and password='a' or 'a'='a'; 很明显,用户名和密码都不对,却可以查询出所有数据,可以登录。 3、防止SQL攻击 * 过滤用户输入的数据中是否包含非法字符; * 分步交验!先使用用户名来查询用户,如果查找到了,再比较密码; * 使用PreparedStatement。 4、PreparedStatement是什么? PreparedStatement叫预编译声明! PreparedStatement是Statement的子接口,你可以使用PreparedStatement来替换Statement。 PreparedStatement的好处: * 防止SQL攻击; [不只它可以防!] * 提高代码的可读性,以可维护性; * 提高效率。 [很重要!] 5、PreparedStatement的使用 * 使用Connection的prepareStatement(String sql):即创建它时就让它与一条SQL模板绑定; * 调用PreparedStatement的setXXX()系列方法为问号设置值 * 调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法; --------------------------------------- // 加载驱动类 Class.forName("com.mysql.jdbc.Driver"); // 得到Connection Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword); /* * 一、得到PreparedStatement * 1. 给出sql模板:所有的参数使用占位符? 来替代 * 2. 调用Connection方法,得到PreparedStatement */ String sql = "select * from t_user where username=? and password=?"; PreparedStatement pstmt = con.prepareStatement(sql); /* * 二、为参数赋值 */ pstmt.setString(1, "zhangsan");//给第1个问号赋值,值为username pstmt.setString(2, "123");//给第2个问号赋值,值为password ResultSet rs = pstmt.executeQuery();//调用查询方法,向数据库发送查询语句,没有参数。 rs.close(); //立即释放此 ResultSet 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。 pstmt.clearParameters(); // 再次使用时需要把当前参数值清除。 pstmt.setString(1, "liSi"); pstmt.setString(2, "123"); pstmt.executeQuery(); --------------------------------------- 在使用Connection创建PreparedStatement对象时需要给出一个SQL模板,所谓SQL模板就是有"?"的SQL语句,其中"?"就是参数。 在得到PreparedStatement对象后,调用它的setXXX()方法为"?"赋值,这样就可以得到把模板变成一条完整的SQL语句, 然后再调用PreparedStatement对象的executeQuery()方法获取ResultSet对象。 注意: Statement的 ResultSet executeQuery(String sql)、int executeUpdate(String sql)方法是需要参数(SQL语句)的; PreparedStatement对象独有的 ResultSet executeQuery()、int executeUpdate() 方法是没有参数的。 因为在创建PreparedStatement对象时已经让它与一条SQL模板绑定在一起了, 所以在调用它的executeQuery()和executeUpdate()方法时就不再需要参数了。 PreparedStatement最大的好处就是在于重复使用同一模板,给予其不同的参数来重复的使用它。这才是真正提高效率的原因。 所以,建议大家在今后的开发中,无论什么情况,都去需要PreparedStatement,而不是使用Statement。
JDBC接口———PreparedStatement预处理
猜你喜欢
转载自blog.csdn.net/weixin_42472048/article/details/82827147
今日推荐
周排行