JDBC课程4--使用PreparedStatement进行增删查改, JDBCTools新增对应的的功能,模拟SQL注入

Posted 好好学习,天天向上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC课程4--使用PreparedStatement进行增删查改, JDBCTools新增对应的的功能,模拟SQL注入相关的知识,希望对你有一定的参考价值。

主要内容:

  熟悉了使用PreparedStatement的优势,没有使用封装和使用封装的方法进行实现了;

  以及JDBCTools新增update_sql(String sql,Object...args) 和query_sql(String sql,Object...args)两个功能模块,分别实现了SQL的update和select的功能.

  了解了sql注入,以及实现了模拟注入和PreparedStatement阻止注入的样例.

  PreparedStatement的使用步骤:

  1.创建PreparedStatement,创建同时传入一个sql
    * String sql="insert into examstudent values(?,?,?)";
  * //2.调用PreparedStatement 的setXXX(int index,Object val)设置占位符的值,
    * Index从1开始,
  * //3.使用方法执行SQL语句: 执行 查询 或者 升级 : executeQuery() 或executeUpdate()
    * //因此,省略了SQl语句


1 使用PreparedStatement, 没有使用封装和使用封装的方法进行实现

package day_19;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
/*
SQL 的date()需要传入参数值: preparedStatement().setDate(new java.util.Date().getTime());
 */
/**PreparedStatement  优势:减轻sql语句的大量书写,
 *          1/是Statement的子接口,可以使用其所有方法
 *          2/可以传入带占位符的SQL语句,并且提供了补充占位符变量的方法.
 *          3/可以有效地防止SQL注入!
 *          4/提高性能,使用一次就编译好了sql母句,节省时间;
 *       --------------------
 *     //1.创建PreparedStatement,创建同时传入一个sql
 *         String sql="insert into examstudent values(?,?,?)";
 *     //2.调用PreparedStatement  的setXXX(int index,Object val)设置占位符的值,
 *          Index从1开始,
 *      //3.使用方法执行SQL语句: 执行 查询 或者 升级 :  executeQuery() 或executeUpdate()
 *                 //因此,省略了SQl语句
 */
public class testPreparedStatement {
    @Test   //使用封装进JDBCTools的update_sql(sql,args1)的方法进行测试;最后直接进行preparedStatement.executeUpdate();
    public void test1(){
        String  sql="insert into author(id,author_name,nation,second_nation) " +
                "values(?,?,?,?)";
        Object args1[]=new Object[]{4,"刘慈欣","北京","河北"};
        Object args2[]=new Object[]{5,"瑞","元星","阿斯加特"};
        JDBCTools.update_sql(sql,args1);
        JDBCTools.update_sql(sql,args2);
    }

      //没有使用封装的方法进行
    public void test2(){
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
            connection=JDBCTools.getConnection();
            String sql="insert into author(id,author_name,nation) " +
                    "values(?,?,?,?)";
            preparedStatement =connection.prepareStatement(sql);
            preparedStatement.setInt(1, 3);
            preparedStatement.setString(2, "山枫叶纷飞233");
            preparedStatement.setString(3, "中国");
            //执行Update更新语句
            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(null,preparedStatement,connection);
        }
    }

}

2 JDBC的工具类

package day_19;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**操纵JDBC的工具类,其中封装了一些工具方法
 * Version 1 : getConnection() : 通过读取配置文件从数据库服务器获取一个连接;
 * Version 2 :  release() : 关闭数据库资源的ResultSet/Statement/Statement
 * Version 3 :  update_sql() : 添加preparedStatement的select的sql的方法
 * Version 4: query_sql() : 执行preparedStatement的的查询操作!
 */
public class JDBCTools {
    /*** 执行sql 语句,使用Preparedstatement
     * @param sql
     * @param args
     */
    public static void update_sql(String sql,Object...args){//添加preparedStatement的update更新sql的方法,同理可以实现 : 增删改
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
            connection = JDBCTools.getConnection();
            preparedStatement=connection.prepareStatement(sql);
            for(int i=0;i<args.length;i++){
                preparedStatement.setObject(i+1, args[i]);
            }
            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            release(null,preparedStatement ,connection);
        }
    }       //添加preparedStatement的select的sql的方法
    public static void query_sql(String sql,Object...args){//执行preparedStatement的的查询操作!
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
            connection = JDBCTools.getConnection();
            preparedStatement=connection.prepareStatement(sql);
            for(int i=0;i<args.length;i++){
                preparedStatement.setObject(i+1, args[i]);
            }
            ResultSet resultSet=null;
            resultSet=preparedStatement.executeQuery();//执行查询操作!
            if(resultSet.next())
                System.out.println("RsultSet查询已经就绪!");
            else
                System.out.println("数据表为空或者404!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            release(null,preparedStatement ,connection);
        }
    }
    public static void release(ResultSet rs,Statement statement, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e2) {
                e2.printStackTrace();
            }
        }
    }
    public static Connection getConnection() throws Exception{
        //1.准备数据库的连接的四个字符串
        String driverClass=null,jdbcUrl=null,user=null,password=null;
        //jdbc:mysql:///books   ;也可以将localhost省略掉!
        //2.读取类路径下的jdbc.properties 文件
        InputStream in=
                JDBCTools.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties =new Properties();
        properties.load(in);
        driverClass =properties.getProperty("driver");
        jdbcUrl=properties.getProperty("jdbcUrl");
        user = properties.getProperty("user");
        password = properties.getProperty("password");
        //3.加载数据库驱动程序(注册驱动),driver对应的实现类中有注册驱动的静态代码块
        // Class.forName(driverClass);  //
        //或这么手动加载,也可以注册多个数据库连接的代码块
        //DriverManager.registerDriver( Class.forName(driverClass).newInstance());

        //4.通过DriverManager 的getConnection()方法获取数据库连接。
        Connection connection=DriverManager.getConnection(jdbcUrl,user,password);
        System.out.print(connection);   //[email protected]

        return connection;
    }
}

3  testSQLInjection 

package day_19;

import org.junit.Test;

import javax.swing.text.DocumentFilter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class testSQLInjection {
    /**使用
     *
     */
    @Test     //因为匹配结果恒真,就可以进行SQL注入!使用PreparedStatement可以避免这个问题!
    public  void testSQLInjection(){
        String username = "a‘ OR PASSWORD = ";
        String password = " OR ‘1‘=‘1";

        String sql = "SELECT * FROM users WHERE username = ‘" + username
                + "‘ AND " + "password = ‘" + password + "‘";

        System.out.println(sql);
        Connection connection=null;
        Statement statement=null;
        ResultSet resultSet=null;

        try {
            connection=JDBCTools.getConnection();
            statement=connection.createStatement();
            resultSet=statement.executeQuery(sql);
            if(resultSet.next())
                System.out.println("登陆成功!");
            else
                System.out.println("404 ! ");
            /*******/
            System.out.println("PreparedStatement测试结果为:");
            String sql2 = "SELECT * FROM users WHERE username = ? AND  password = ?";
            JDBCTools.query_sql(sql2,username,password);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCTools.release(resultSet, statement,connection );
        }

    }
}

 

以上是关于JDBC课程4--使用PreparedStatement进行增删查改, JDBCTools新增对应的的功能,模拟SQL注入的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JDBC4PreparedStatement 与期望 OUT 参数的 MySQL 存储过程一起使用?

JDBC课程4--使用PreparedStatement进行增删查改, JDBCTools新增对应的的功能,模拟SQL注入

第十四周课程总结&实验报告

JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法

第十四周课程总结&实验报告(简单记事本的实现)

java内存溢出