PreparedStatement 預編譯防止sql注入

原文地址
https://blog.csdn.net/tang_2214/article/details/80349557

PreparedStatement爲什麼能在一定程度上防止SQL注入?
PreparedStatement會對SQL進行了預編譯,在第一次執行SQL前數據庫會進行分析、編譯和優化,同時執行計劃同樣會被緩存起來,它允許數據庫做參數化查詢。在使用參數化查詢的情況下,數據庫不會將參數的內容視爲SQL執行的一部分,而是作爲一個字段的屬性值來處理,這樣就算參數中包含破環性語句(or ‘1=1’)也不會被執行。

怎麼使用PreparedStatement?如何避免SQL注入式攻擊?PreparedStatement與Statement有什麼區別,有什麼樣的優勢?

============================================================================

一個PreparedStatement簡單例子

public class JDBCTest {
    public static void main(String[] args) {
        //表示使用Unicode字符集;字符編碼設置爲utf-8;不使用SSL連接
        String URL = "jdbc:mysql://127.0.0.1:3306/sampledb?useUnicode=true&" +
                "characterEncoding=utf-8&useSSL=false";
        String USER = "spring4";//用戶
        String PASSWORD = "spring4";//密碼
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            //1.加載驅動程序到JVM
            Class.forName("com.mysql.jdbc.Driver");
            //2.創建數據庫連接
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
            //3.創建Statement,實現增刪改查
            String sql = "select user_id,user_name,credits from t_user where credits > ?";
            st = conn.prepareStatement(sql);//這裏使用PreparedStatement
            st.setInt(1, 8);
            //4.向數據庫發送SQL命令
            rs = st.executeQuery();
            //5.使用ResultSet處理數據庫的返回結果
            while (rs.next()) {
                System.out.println(rs.getLong("user_id") + " "
                        + rs.getString("user_name") + " "
                        + rs.getString("credits"));
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            //6.關閉資源
            try {
                rs.close();
                st.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

Statement的幾種實現

Statement 對象用於將SQL語句發送到數據庫中。
Statement每次執行SQL語句,數據庫都要執行SQL語句的編譯,最好用於僅執行一次查詢並返回結果的情形
1、執行靜態SQL語句。通常通過Statement實例實現。
2、執行動態SQL語句。通常通過PreparedStatement實例實現。
3、執行數據庫存儲過程。通常通過CallableStatement實例實現。

‘#’和‘$’的區別

sql 預編譯指的是數據庫驅動在發送 sql 語句和參數給 DBMS 之前對 sql 語句進行編譯,這樣 DBMS 執行 sql 時,就不需要重新編譯。
‘#{ }’:解析爲一個 JDBC 預編譯語句(prepared statement)的參數標記符,一個‘ #{ }’ 被解析爲一個參數佔位符 ? 。
‘${ }’ 僅僅爲一個純粹的 string 替換,在動態 SQL 解析階段將會進行變量替換。在預編譯之前已經被變量替換了
‘${ }’變量的替換階段是在動態 SQL 解析階段,而’#{ }’變量的替換是在 DBMS 中。

PreparedStatement與Statement有什麼區別

1.PreparedStatement能預編譯,這條預編譯的SQL查詢語句能在將來的查詢中重用,這樣一來,它比Statement對象生成的查詢速度更快。
2.PreparedStatement可以寫動態參數化的查詢
3.PreparedStatement可以防止SQL注入式攻擊
4.PreparedStatement查詢可讀性更好,追加條件的語句很亂
5.PreparedStatement不允許一個佔位符(?)有多個值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章