PreparedStatement不允許在插入參數時改變SQL語句的邏輯結構。
為什么它這樣處理就能預防SQL注入提高安全性呢?其實是因為SQL語句在程序運行前已經進行了預編譯,在程序運行時第一次操作數據庫之前,SQL語句已經被數據庫分析,編譯和優化,對應的執行計划也會緩存下來並允許數據庫已參數化的形式進行查詢,當運行時動態地把參數傳給PreprareStatement時,即使參數里有敏感字符如 or '1=1'也數據庫會作為一個參數一個字段的屬性值來處理而不會作為一個SQL指令,如此,就起到了防止SQL注入的作用了!
經常碰到這樣的面試題目:#{}和${}的區別是什么?
網上的答案是:
#{}是預編譯處理,$ {}是字符串替換。
mybatis在處理#{}時,會將sql中的#{}替換為?號,調用PreparedStatement的set方法來賦值,使用 #{} 可以有效的防止SQL注入,提高系統安全性。
mybatis在處理 $ { } 時,就是把 ${ } 替換成變量的值。
對於這個題目我感覺要抓住幾點:
(1)#{}是預編譯處理,MyBatis在處理#{ }時,它會將sql中的#{ }替換為?,然后調用PreparedStatement的set方法來賦值,傳入字符串后,會在值兩邊加上單引號,如上面的值 “4,44,514”就會變成“ ‘4,44,514’ ”;
(2)預編譯的機制。預編譯是提前對SQL語句進行預編譯,而其后注入的參數將不會再進行SQL編譯。我們知道,SQL注入是發生在編譯的過程中,因為惡意注入了某些特殊字符,最后被編譯成了惡意的執行操作。而預編譯機制則可以很好的防止SQL注入。
(3)
是字符串替換,在處理是字符串替換,MyBatis在處理時,它會將sql中的{ }替換為變量的值,傳入的數據不會加兩邊加上單引號。
- ${param}傳遞的參數會被當成sql語句中的一部分,比如傳遞表名,字段名
- 例子:(傳入值為id)
- order by ${param}
- 則解析成的sql為:order by id
而使用${}在動態解析時候,會傳入參數字符串
select * from student where student_name = 'lyrics'
- #{parm}傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號
- 例子:(傳入值為id)
- select * from table where name = #{param}
- 則解析成的sql為:
- select * from table where name = "id"
select * from student where student_name = #{name}
預編譯后,會動態解析成一個參數標記符?:
select * from student where student_name = ?
-
#{} 這種取值是編譯好SQL語句再取值
-
${} 這種是取值以后再去編譯SQL語句
為了安全,能用#的地方就用#方式傳參,這樣可以有效的防止sql注入攻擊。
MyBatis排序時使用order by 動態參數時需要注意,用$而不是#,$一般用入傳入數據庫對象,比如數據庫表名;
sql注入簡介
直接上了百度的例子,感覺一看就清晰明了
某個網站的登錄驗證的SQL查詢代碼為:
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
惡意填入
userName = "1' OR '1'='1";
與passWord = "1' OR '1'='1";
時,將導致原本的SQL字符串被填為
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"
也就是實際上運行的SQL命令會變成下面這樣的
strSQL = "SELECT * FROM users;"
這樣在后台帳號驗證的時候巧妙地繞過了檢驗,達到無賬號密碼,亦可登錄網站。所以SQL注入攻擊被俗稱為黑客的填空游戲。
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
惡意填入
userName = "1' OR '1'='1";
與passWord = "1' OR '1'='1";
時,將導致原本的SQL字符串被填為
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"
也就是實際上運行的SQL命令會變成下面這樣的
strSQL = "SELECT * FROM users;"
這樣在后台帳號驗證的時候巧妙地繞過了檢驗,達到無賬號密碼,亦可登錄網站。所以SQL注入攻擊被俗稱為黑客的填空游戲。