JDBC之PreparedStatement
来源:互联网 发布:淘宝侵权怎么处理 编辑:程序博客网 时间:2024/06/06 10:05
这里介绍个Statement的子类PreparedStatement.
PreparedStatement(预处理执行语句)相比其父类Statement主要有以下几个优点.
1.可以防止SQL注入.
2.在特定的驱动数据库下相对效率要高(不绝对)
3.不需要频繁编译.因为已经预加载了
这里2和3的优点就不具体分析.这里主要讲解下防止SQL注入这一用途.
什么叫SQL注入可以阅读下WIKI.这里还是使用上一节总结的DBUtils来讲解.
DBUtils辅助类
package com.test.jdbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/** * @author Administrator * 模板类DBUtils */public final class DBUtils { // 参数定义 private static String url = "jdbc:mysql://localhost:3306/mytest"; // 数据库地址 private static String username = "root"; // 数据库用户名 private static String password = "root"; // 数据库密码 private DBUtils() { } // 加载驱动 static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { System.out.println("驱动加载出错!"); } } // 获得连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } // 释放连接 public static void free(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); // 关闭结果集 } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (st != null) { st.close(); // 关闭Statement } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (conn != null) { conn.close(); // 关闭连接 } } catch (SQLException e) { e.printStackTrace(); } } } }}
在写sql注入演示类之前看下数据库结构:
上边就是简单的users表.然后看下SQL注入演示类
SQLInner
package com.test.jdbc;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class SqlInner { public static void main(String[] args) { //Read("zhangsan"); // 如果普通查询可以 Read("' or 1 or'"); } public static void Read(String name) { Statement st = null; ResultSet rs = null; Connection conn = null; try { conn = DBUtils.getConnection(); st = conn.createStatement(); String sql = "select * from users where lastname = '" + name + "'"; // 主要注入发生地 System.out.println("sql: " + sql); // 打印SQL语句 rs = st.executeQuery(sql); System.out.println("age\tlastname\tfirstname\tid"); while (rs.next()) { System.out.println(rs.getInt(1) + "\t" + rs.getString(2) + "\t\t" + rs.getString(3) + "\t\t" + rs.getString(4)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.free(rs, st, conn); } }}见注释.如果用普通的键zhangsan来查询.会打印
age lastname firstname id23 zhangsan lisi 3结果正常.但使用下面的' or 1 or'结果为
age lastname firstname id22 啡 咖 125 434 ni 223 zhangsan lisi 3把所有结果都打印出来了.打印了一下生成后的SQL语句如下:
sql: select * from users where lastname = '' or 1 or''
分析下不难看出.主要问题是用了两个单引号 分别把前后的两个''给封闭了 变成两个空 然后通过or 1即or true就是符合所有条件了.
这就是SQL注入的一种.为了避免这种情况可以使用特殊符号替换 但只是亡羊补牢. 下面就引出了PreparedStatement
package com.test.jdbc;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class SqlInner { public static void main(String[] args) { Read("' or 1 or'"); } public static void Read(String name) { PreparedStatement st = null; ResultSet rs = null; Connection conn = null; try { conn = DBUtils.getConnection(); String sql = "select * from users where lastname = ?"; // 这里用问号 st = conn.prepareStatement(sql); st.setString(1,name); // 这里将问号赋值 rs = st.executeQuery(); System.out.println("age\tlastname\tfirstname\tid"); while (rs.next()) { System.out.println(rs.getInt(1) + "\t" + rs.getString(2) + "\t\t" + rs.getString(3) + "\t\t" + rs.getString(4)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.free(rs, st, conn); } }}
见注释.PreparedStatement用?代替变量.然后加载后setString给赋值.由于PreparedStatement内置了字符过滤
那么就相当于 where name = ' or 1 or '显然没有对应记录.所以数据结果为空.这就体现了PreparedStatement的防注入功能
所以提倡大家只要是动态参数就是用PreparedStatement去代替Statement.况且效率也不错.优化的很好.
其余JDBC介绍文章待续.
0 0
- JDBC基础教程之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC 之 PreparedStatement 接口
- JDBC基础教程之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC基础教程之PreparedStatement
- JDBC之PreparedStatement
- Java JDBC 之 PreparedStatement
- JDBC之PreparedStatement
- JDBC之PreparedStatement
- JDBC之preparedStatement
- JDBC之PreparedStatement接口
- JDBC基础教程之PreparedStatement (引用)
- JDBC学习之二PreparedStatement
- Java 时间和日期类型的 Hibernate 映射及二进制映射及大文本的映射
- 输入三条边,判断是否可构成三角形
- linux多线程设计
- 三个数的最大值
- javaweb项目中引入struts2后web.xml的详细配置和注释
- JDBC之PreparedStatement
- 有一函数,编写一个程序,从键盘输入一个x值,程序输出y的值
- 王朝 书
- 【NOIP2016提高A组集训第1场10.29】完美标号
- android ANR
- java的Observable类中,notifyObservers(Object arg)和notifyObservers()的区别
- 为什么极大似然估计得到的方差是有偏估计
- http://blog.csdn.net/woshizhangliang999/article/details/51649461
- 王朝 钱得分配