JDBC之SQL注入,PreparedStatement和Statement

来源:互联网 发布:知行家 编辑:程序博客网 时间:2024/05/21 11:29
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 */@Testpublic void testStatement() throws SQLException {//readByStatement("lisi");//这里表示值是'或者1或者',即单引号readByStatement("' or 1 or '");}/** * 使用这种方式经过测试查询不出结果 * @throws SQLException */@Testpublic 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方法,打印不出任何结果。

原创粉丝点击