1. 程式人生 > >jdbc_012_使用jdbc操作實現登入操作並且演示SQL注入攻擊

jdbc_012_使用jdbc操作實現登入操作並且演示SQL注入攻擊

一、建庫及表語句(簡單測試)

drop database db_test;
create database db_test;
use db_test;
create table user(
    userId int(5) primary key comment '使用者id',
    userName varchar(16) comment '使用者姓名',
    userPw varchar(16) comment '使用者密碼'
);
insert into user(userId,userName,userPw) values(10001,'user1','user1
'); insert into user(userId,userName,userPw) values(10002,'user2','user2'); insert into user(userId,userName,userPw) values(10003,'user3','user3'); insert into user(userId,userName,userPw) values(10004,'user4','user4'); insert into user(userId,userName,userPw) values(10005,'user5','user5');

二、封裝jdbc的工具類(同上集)

package edu.aeon.aeonutils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * [說明]:jdbc工具類
 * 封裝了jdbc裡面的重複步驟:資料庫的連線和資料庫資源的釋放
 * 
@author aeon * @version 1.2(該版本將連線資料庫的各種資料庫配置資訊(使用者名稱、密碼、驅動及url)單獨提取到配置檔案中) */ public class AeonJdbcUtils { private static String username; private static String password; private static String driverClass; private static String url; /** * 靜態程式碼塊處理讀取之前的資料 */ static{ InputStream inputStream = AeonJdbcUtils.class.getClassLoader().getResourceAsStream("config/database/database.properties"); Properties properties=new Properties(); try { properties.load(inputStream); username = properties.getProperty("username"); password = properties.getProperty("password"); driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); } catch (IOException e) { System.out.println("初始化讀取資料庫配置檔案--->database.properties失敗!"); e.printStackTrace(); } } /** * 連線資料庫 * @return 資料庫連線物件 * @throws ClassNotFoundException * @throws SQLException */ public static Connection getMySqlConnection() throws ClassNotFoundException, SQLException{ Class.forName(driverClass); return DriverManager.getConnection(url, username, password); } /** * 釋放資料庫資源 * @param resultSet 結果集 * @param statement 執行sql語句的物件 * @param connection 資料庫連線物件 */ public static void closeDB(ResultSet resultSet,Statement statement,Connection connection){ if(null!=resultSet){ try { resultSet.close(); } catch (SQLException e) { System.out.println("釋放資料庫資源失敗!--->resultSet"); e.printStackTrace(); } } if(null!=statement){ try { statement.close(); } catch (SQLException e) { System.out.println("釋放資料庫資源失敗!--->statement"); e.printStackTrace(); } } if(null!=connection){ try { connection.close(); } catch (SQLException e) { System.out.println("釋放資料庫資源失敗!--->connection"); e.printStackTrace(); } } } }

三、包檢視截圖:

  

四、資料庫配置資訊database.properties  

 username=root
 password=root
 driverClass=com.mysql.jdbc.Driver
 url=jdbc:mysql://localhost:3306/db_test

五、資料庫截圖資訊:

  

 

六、使用者登入

package edu.aeon.logon;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

import edu.aeon.aeonutils.AeonJdbcUtils;
/**
 * [說明]:實現使用者登入、並且演示sql注入攻擊
 * 造成sql注入攻擊的原因
 *     1.and和or的優先順序(and(可以理解為並且)優先與or(可以理解為或者))其實是構造or的條件來無視and條件()
 *     2.sql語句的拼接
 * 如何解決sql注入攻擊?
 *     資料庫and 和 or的優先順序天生的、我們無法改變
 *     唯一解決思路:改變sql語句的拼接、(詳見下集)
 * @author aeon
 *
 */
public class UserLogon {
    /**
     * 封裝鍵盤輸入
     * @return
     */
    public static Map<String, String> ReadBoard(){
        /**
         * 鍵盤掃描器:掃描鍵盤輸入的內容
         */
        Scanner scanner=new Scanner(System.in);
        System.out.println("請輸入使用者名稱:");
        String username=scanner.nextLine();//以\n作為一行的標識來讀取一行
        System.out.println("請輸入密碼:");
        String password=scanner.nextLine();
        Map<String, String> userMap=new HashMap<String, String>();
        //將鍵盤輸入的內容封裝到map集合中、並且返回給呼叫者
        userMap.put("username", username);
        userMap.put("password", password);
        return userMap;
    }
    /**
     * 使用者登入具體實現
     * @return 登入成功標誌 true則登入成功、否則失敗!
     */
    public static boolean userLogon(){
        boolean flag=false;
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            //連線資料庫
            connection = AeonJdbcUtils.getMySqlConnection();
            //獲得執行sql語句物件
            statement = connection.createStatement();
            //獲取到使用者輸入的資料
            Map<String, String> userMap=ReadBoard();
            //登入sql
            String logonSql="select * from user where username='"+userMap.get("username")+"' and userpw ='"+userMap.get("password")+"'";
            System.out.println("登入的sql語句為:"+logonSql);
            resultSet = statement.executeQuery(logonSql);
            if(resultSet.next()){ //如果資料庫中有記錄則將登入標誌flag置為true
                flag = true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 使用者登入測試
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(userLogon()?"使用者登入成功!":"使用者登入失敗!");
    }
}

 執行結果截圖(我們輸入資料庫中根本不存在的使用者和密碼):

  

 執行結果截圖(我們輸入資料庫中存在的使用者和其對應密碼):

  

執行結果截圖(構造sql注入攻擊):

  

 用or來使的前面and條件無效、其實這條sql攻擊語句最後執行等同於:select * from user where 'x'='x'

我們可以看出where條件永遠為真。