jdbc_012_使用jdbc操作實現登入操作並且演示SQL注入攻擊
阿新 • • 發佈:2018-12-05
一、建庫及表語句(簡單測試)
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條件永遠為真。