首頁 > 常見問題 > 為什麼預編譯可以防止sql注入

為什麼預編譯可以防止sql注入

(*-*)浩
發布: 2020-09-15 17:55:56
原創
12647 人瀏覽過

預先編譯可以防止sql注入的原因:允許資料庫做參數化查詢。在使用參數化查詢的情況下,資料庫不會將參數的內容視為SQL執行的一部分,而是作為一個欄位的屬性值來處理,這樣就算參數中包含破環性語句(or '1=1' )也不會被執行。

為什麼預編譯可以防止sql注入

PreparedStatement為什麼能在某種程度上防止SQL注入?

PreparedStatement會對SQL進行了預編譯,在第一次執行SQL前資料庫會進行分析、編譯和最佳化,同時執行計畫同樣會被快取起來,它允許資料庫做參數化查詢。在使用參數化查詢的情況下,資料庫不會將參數的內容視為SQL執行的一部分,而是作為一個欄位的屬性值來處理,這樣就算參數中包含破環性語句(or '1=1' )也不會被執行。

推薦課程:Java教學

怎麼使用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不允許一個佔位符(?)有多個值

以上是為什麼預編譯可以防止sql注入的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
sql
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板