在php編寫程式中,我們可以使用類似如下的PDO預先處理綁定語句來有效防止sql注入問題:
$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (:name, :value)" );$stmt -> bindParam ( ':name' , $name );$stmt -> bindParam ( ':value' , $value );$name = 'one' ;$value = 1 ;$stmt -> execute ();
或者使用?號預留位置來達到相同的效果:
$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)" );
筆者有一點表示很不理解,就是在PDO底層是如何處理該sql語句的,可以這麼有效防止注入問題。
請大家指點一下...thanks
回複內容:
在php編寫程式中,我們可以使用類似如下的PDO預先處理綁定語句來有效防止sql注入問題:
$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (:name, :value)" );$stmt -> bindParam ( ':name' , $name );$stmt -> bindParam ( ':value' , $value );$name = 'one' ;$value = 1 ;$stmt -> execute ();
或者使用?號預留位置來達到相同的效果:
$stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)" );
筆者有一點表示很不理解,就是在PDO底層是如何處理該sql語句的,可以這麼有效防止注入問題。
請大家指點一下...thanks
大部分常見資料庫都支援prepare語句,以postgresql為例
PREPARE fooplan (int, text, bool, numeric) AS INSERT INTO foo VALUES($1, $2, $3, $4);EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);
第一句把insert prepare成為名為fooplan的statement,第二句用具體的資料去execute fooplan statement
注意,fooplan是當前資料庫連接中有效,另一個資料庫連接就不能直接execute fooplan
在資料庫支援prepare特性的情況下,PDO就使用資料庫的prepare語句來實現
$fooplan = $pdo->prepare('INSERT INTO foo VALUES(?, ?, ?, ?)');$fooplan->execute(array(1, 'Hunter Valley', 't', 200.00));
和sql對照一看是不是就明白了
因為prepare ... execute這個特性實在太有用,所以即使資料庫不支援prepare,pdo也會採用類比的方式來實現,簡單來說就是pdo自己對資料做quote,然後把結果拼接成sql再執行
還有一種特殊情況就是串連池,比如我用pgbouncer做postgresql串連池,串連池是transaction或statement模式。在這個模式下,每條語句都可能使用的不同的串連
所以pdo就沒法使用到資料庫的prepare特性,因為prepare和execute兩條語句可能使用不同的串連,在這種情況下就必須強制使用pdo的類比prepare方式才行
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
之前學參數化查詢的時候看過的一篇Blog 供題主參考
參數化查詢為什麼能夠防止SQL注入- LoveJenny - 部落格園
對每個 pram 運行 PDO:quote.
http://php.net/manual/zh/pdo.quote.php
@runner_sam 你的推薦部落格確實值得參考,而且分析的也很詳盡,不失為一篇好的部落格文章,謝謝你了。
這裡筆者再推薦一篇文章,說明了PDO防注入原理分析以及使用PDO的注意事項,特此推薦給大家,僅供參考,共同進步...