1. 程式人生 > >JDBC課程4--使用PreparedStatement進行增刪查改, JDBCTools新增對應的的功能,模擬SQL注入

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 );
        }

    }
}