PDO防止sql注入的機制

使用PDO訪問MySQL數據庫時,真正的real prepared statements 默認情況下是不使用的。為了解決這個問題,你必須禁用 prepared statements的仿真效果。下面是使用PDO創建鏈接的例子:

代碼如下:

$dbh?=?new?PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8',?'user',?'pass');  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,?false);

setattribute() 這一行是強制性的,它會告訴 pdo 禁用模擬預處理語句,并使用 real parepared statements 。這可以確保sql語句和相應的值在傳遞到mysql服務器之前是不會被php解析的(禁止了所有可能的惡意sql注入攻擊)。雖然你可以配置文件中設置 字符集的屬性(charset=utf8),但是需要格外注意的是,老版本的 php(

我們來看一段完整的代碼使用實例:

代碼如下:

$dbh?=?new?PDO("mysql:host=localhost;?dbname=dbtest",?"user",?"pass");  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,?false);?//禁用prepared?statements的仿真效果  $dbh->exec("set?names?'utf8'");  $sql="select?*?from?test?where?name?=???and?password?=??";  $stmt?=?$dbh->prepare($sql);  $exeres?=?$stmt->execute(array($testname,?$pass));  if?($exeres)?{  ?while?($row?=?$stmt->fetch(PDO::FETCH_ASSOC))?{  ?????print_r($row);  ?}  }  $dbh?=?null;

上面這段代碼就可以防范sql注入。為什么呢?

當調用 prepare() 時,查詢語句已經發送給了數據庫服務器,此時只有占位符 ? 發送過去,沒有用戶提交的數據;當調用到 execute()時,用戶提交過來的值才會傳送給數據庫,他們是分開傳送的,兩者獨立的,SQL攻擊者沒有一點機會。

但是我們需要注意的是以下幾種情況,PDO并不能幫助你防范SQL注入

1、你不能讓占位符 ? 代替一組值,如:

代碼如下:

SELECT?*?FROM?blog?WHERE?userid?IN?(???);

2、你不能讓占位符代替數據表名或列名,如:

代碼如下:

SELECT?*?FROM?blog?ORDER?BY??;

3、你不能讓占位符 ? 代替任何其他SQL語法,如:

代碼如下:

SELECT?EXTRACT(???FROM?datetime_column)?AS?variable_datetime_element?FROM?blog;

?以上就是PDO防止sql注入的機制的內容,更多相關內容請關注PHP中文網(www.php.cn)!

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享