Java-JDBC-PreparedStatement和SQL注入

Java-JDBC-PreparedStatement和SQL注入


目錄




內容

1、登錄案例

  • 需求:輸入用戶名和密碼,如果用戶名和密碼同數據庫中存儲的用戶名和密碼相同,則運行登錄,否則不允許登錄

  • 步驟:

    • 創建login表

      • username字段

      • password字段

          create table login(
          id int primary key auto_increment,
          username varchar(20) not null,
          password varchar(100) not null
          );
        
    • 插入測試數據

        insert into login(username, password) values ('zhangsan', 'a123'), 
        ('lishi', '3f2f3');
      
    • 圖示1-1:[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pE2TSm8B-1592487282529)(./images/login.png)]

    • 編寫登錄邏輯

        package cn.gaogzhen.jdbc;
      
        import java.sql.Connection;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        import java.sql.Statement;
        import java.util.ArrayList;
        import java.util.Date;
        import java.util.List;
        import java.util.Scanner;
      
        import cn.gaogzhen.domain.Emp;
        import cn.gaogzhen.util.JDBCUtils;
      
        public class JDBCDemo7 {
        	public static void main(String[] args) throws SQLException {
        		Scanner sc = new Scanner(System.in);
        		System.out.println("請輸入用戶名:");
        		String username = sc.nextLine().trim();
        		System.out.println("請輸入密碼:");
        		String password = sc.nextLine().trim();
        		String res = login(username, password)? "登錄成功": "登錄失敗";
        		System.out.println(res);
        	 }
      
        	public static boolean login(String username, String password) throws SQLException {
        		if(username == null || password == null) return false;
        		Connection conn = JDBCUtils.getConnection();
        		String sql = "select * from login where username = '" + username +"' and password = '" + password + "'";
        		Statement stmt = conn.createStatement();
        		ResultSet rs = stmt.executeQuery(sql);
        		boolean flag = rs.next();
        		JDBCUtils.close(rs, stmt, conn);
        		return flag;
        	}
        }
      
    • 測試結果:

        // 成功
        請輸入用戶名:
        zhangsan
        請輸入密碼:
        a123
        登錄成功
        // 失敗
        請輸入用戶名:
        fewf
        請輸入密碼:
        fwfe
        登錄失敗
      
  • 注意:JDBCUtils類爲上一篇JDBCUtils工具類博文中編寫的工具類

2、SQL注入

  在#1登錄案例中,如何密碼輸入

as' or '1' = '1# 

用戶名隨意,試一下會發生什麼?
測試結果:

請輸入用戶名:
fasdfa
請輸入密碼:
sfas' or '1'='1
登錄成功

  這就是SQL注入問題,關於SQL注入的詳情,有興趣的小夥伴可自行查閱相關文檔。那麼這裏怎麼解決SQL注入問題呢?這就是需要用到下面要介紹的PreparedStatement對象。

3、PreparedStatement

  • 表示預編譯的SQL語句的對象:用?代替參數
  • 步驟
    1. 導入jar包:mysql-connector-java-版本號-bin.jar
    2. 註冊驅動
    3. 獲取連接對象Connection
    4. sql語句
      • 注意:sql語句的參數使用?作爲佔位符,如select * from login where username = ? and password = ?
    5. 獲取執行sql語句的對象PreparedStatement
    6. 給?賦值
      • 方法:setXXX(參數1, 參數2)
        • 參數1:?的位置編號,從1開始
        • 參數2:?的值
    7. 執行sql操作
    8. 得到結果
    9. 解析結果
    10. 釋放資源

  那麼我們現在使用PreparedStament類對象防止上面的SQL注入

  • 實現代碼3-1:

      package cn.gaogzhen.jdbc;
    
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.Scanner;
    
      import cn.gaogzhen.util.JDBCUtils;
    
      public class JDBCDemo8 {
      	public static void main(String[] args) throws SQLException {
      		Scanner sc = new Scanner(System.in);
      		System.out.println("請輸入用戶名:");
      		String username = sc.nextLine().trim();
      		System.out.println("請輸入密碼:");
      		String password = sc.nextLine().trim();
      		sc.close();
      		String res = login(username, password)? "登錄成功": "登錄失敗";
      		System.out.println(res);
       }
    
      	public static boolean login(String username, String password) throws SQLException {
      		if(username == null || password == null) return false;
      		Connection conn = JDBCUtils.getConnection();
      		String sql = "select * from login where username = ? and password = ?";
      		PreparedStatement pstm = conn.prepareStatement(sql);
      		pstm.setString(1, username);
      		pstm.setString(2, password);
      		ResultSet rs = pstm.executeQuery();
      		boolean flag = rs.next();
      		JDBCUtils.close(rs, pstm, conn);
      		return flag;
      	}
      }
    

測試結果:

請輸入用戶名:
sdfasf
請輸入密碼:
sdfas' or '1'='1#
登錄失敗

後記

本項目爲參考某馬視頻開發,相關視頻及配套資料可自行度娘或者聯繫本人。上面爲自己編寫的開發文檔,持續更新。歡迎交流,本人QQ:806797785

前端項目源代碼地址:https://gitee.com/gaogzhen/vue-leyou
後端JAVA源代碼地址:https://gitee.com/gaogzhen/JAVA
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章