1. 程式人生 > 其它 >【JDBC】學習路徑3-密碼登入&SQL注入攻擊

【JDBC】學習路徑3-密碼登入&SQL注入攻擊

最後再提醒一句,每次在測試JDBC程式的時候,一定要確保MySQL正在執行。

開啟控制檯(終端),輸入mysql

如果沒啟動,則出現以下提示:

Mac端啟動MySQL資料庫,需要在系統便好設定中啟動。


第一章:構建登入校驗客戶端

測試資料庫:

當用戶輸入了正確的賬號密碼時,這個函式返回true,反之。

檢視程式碼
public static boolean selectWithUsernamePassword(String username,String password){
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //註冊驅動
            Class.forName("com.mysql.cj.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/jdbc_01?useUnicode=true&characterEncoding=UTF8";

            con = DriverManager.getConnection(url,"root","88888888");

            stmt = con.createStatement();

            String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";
            System.out.println(sql);
            rs = stmt.executeQuery(sql);

            if(rs.next())
                return true;
            else
                return false;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (stmt != null)
                    stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (con != null)
                    con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

其中,這一行時我們組拼的SQL語句:

String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";

我們在main方法中呼叫測試一下:

selectWithUsernamePassword("remoo1","1234");

返回的是true;

若輸入了資料庫中不存在的資料,則返回false。


第二章:SQL注入攻擊

當我們密碼輸入為:

selectWithUsernamePassword("nijsfies","1sadf' or '1'='1");

時,我們發現,無論你密碼是否正確,最後都會輸出true。

 我們組拼的完整的SQL語句如下:

select * from user where username ='nijsfies'and password ='1234' or '1'='1'

相當於:select * from user where (username ='asd' and password = 'asd') or '1'='1'

where後面有兩個條件:使用者名稱密碼滿足xxx、‘1’=‘1’

顯然‘1’=‘1’(SQL語句中等號為=,而不是==),

後面的每一條資料都滿足1=1這個條件,

所以一定返回全部資料。

第三章:阻止SQL注入

如何解決?使用PreparedStatement()

檢視程式碼

public static boolean safe_SelectWithUP(String username,String password){
        Connection con = null;
        //Statement stmt = null;
        ResultSet rs = null;
        PreparedStatement pstmt = null;
        try {
            //註冊驅動
            Class.forName("com.mysql.cj.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/jdbc_01?useUnicode=true&characterEncoding=UTF8";

            con = DriverManager.getConnection(url,"root","88888888");

//            stmt = con.createStatement();
//            String sql = "select * from user where username ='"+username+"'and password ='"+password+"'";
//            System.out.println(sql);
//            rs = stmt.executeQuery(sql);

            //?代表一個引數
            String sql = "select * from user where username = ? and password = ?";

            pstmt = con.prepareStatement(sql);
            pstmt.setString(1,username);
            pstmt.setString(2,password);

            //上面已經傳遞了SQl語句了,這裡直接執行就好了。
            //SQL語句已經儲存在pstmt內部了,並且對SQL注入攻擊進行了防範。
            rs = pstmt.executeQuery();
            System.out.println(sql);


            if(rs.next())
                return true;
            else
                return false;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (pstmt != null)
                    pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (con != null)
                    con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

 測試結果: