本文共 2646 字,大约阅读时间需要 8 分钟。
1、在SQL中包含特殊字符串或SQL的关键字(如:’or 1 or’)时,Statement将出现不可预料的结果(出现异常或查询的结果不正确),可用PreparedStatement来解决。 2、PreparedStatement(从Statement扩展而来)相对Statement的优点: ①没有SQL注入的问题; ②Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出;③数据库和驱动可以对PreparedStatement进行优化(只有在相关联的数据库连接没有关闭的下有效);
④PreparedStatement效率比Statement效率高,但是在第一次执行的时候,PreparedStatement需要进行预编译处理,会比Statement效率低。
3、测试SQL注入SQLInject.java中的代码
package cn.itcast.jdbc;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import org.junit.Test;/** * 演示SQL注入,Statement和PreparedStatement的区别 */public class SQLInject { /** * 这种方式会存在SQL注入的问题 * @throws SQLException */ @Test public void testStatement() throws SQLException { //readByStatement("lisi"); //这里表示值是'或者1或者',即单引号 readByStatement("' or 1 or '"); } /** * 使用这种方式经过测试查询不出结果 * @throws SQLException */ @Test public void testPreparedStatement() throws SQLException { readByPreparedStatement("' or 1 or '"); } /** * 使用PreparedStatement执行查询 * @param name * @throws SQLException */ static void readByPreparedStatement(String name) throws SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try{ //JdbcUtils参见上一篇博客 conn = JdbcUtils.getConnection(); String sql = "select id, name, money, birthday from user where name=?"; //会对SQL语句进行预编译 ps = conn.prepareStatement(sql); //注意下标从1开始 ps.setString(1, name); //执行语句 rs = ps.executeQuery(); //处理结果 while(rs.next()) { System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + "\t" + rs.getDate("birthday") + "\t" + rs.getFloat("money")); } }finally{ JdbcUtils.free(rs, ps, conn); } } /** * 通过Statement查询数据,存在SQL注入的问题 * @param name * @throws SQLException */ static void readByStatement(String name) throws SQLException { Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); conn.getAutoCommit(); st = conn.createStatement(); String sql = "select id, name, money, birthday from user where name='" + name + "'"; System.out.println("SQL:" + sql); rs = st.executeQuery(sql); while(rs.next()) { System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + "\t" + rs.getDate("birthday") + "\t" + rs.getFloat("money")); } } finally { JdbcUtils.free(rs, st, conn); } }}
测试结果:
运行testStatement方法,得到如下结果(数据库中的结果全部被查询来):
SQL:selectid, name, money, birthday from userwhere name='' or 1 or ''
1 zhangsan 2017-06-30 110.0
2 lisi 2017-06-06 210.0
3 wangwu 2017-05-30 310.0
4 name1 1987-01-01 410.0
运行readByPreparedStatement方法,打印不出任何结果。
转载地址:http://cklvb.baihongyu.com/