這篇文章主要是接續前一篇文章〈PHP Data Objects (PDO) 簡易使用說明-啟用PDO讀取資料庫資料〉,進一步說明如何透過prepare來防止可能的sql injection,另外也說明如何在PDO中使用where in ()的query方式。
如何達到sql injection
首先,一般的時候,執行以下指令,我可以獲得我資料庫裡的所有內容:
#查詢Query的結果 $sql = 'select * from pdo'; $statement = $connection->query($sql); echo "<pre>"; print_r($statement->fetchALL(PDO::FETCH_ASSOC)); echo "</pre>";
結果像是這樣:
如果我想要限制,只要取出sn = 11的資料時,我可以把程式改成:
#查詢Query的結果
$sn = 11;
$sql = "select * from pdo where sn = $sn";
$statement = $connection->query($sql);
這時候便只會得到得到sn = 11的資料。
然後,若有心人士透過某些方法,把$sn = 11 改成$sn = 11 or 1,這時候他就可以撈出我們資料庫中所有的資料!
#查詢Query的結果
$sn =' 11 or 1';
$sql = "select * from pdo where sn = $sn";
$statement = $connection->query($sql);
prepared指令的使用
當我們使用$statement->query()的方式來擷取資料時,PDO會在內部先準備好一個指令,然後執行它。
當你使用的是$statement->prepared()時,你會先創造一個prepared的聲明(prepared statement),並且說明哪些是placeholder,會在之後的地方才放入。
當你之後執行$statement->execute()時,你再把屬於該placeholder的值放入,並且加以執行。
舉例來說:
我們可以先把我們sql改成如下,在變數前面加上冒號(:)表示它是placeholder,我們會在之後execute的時候再來填入它:
$sql = "select * from pdo where sn = :sn";
接著,把原本的query改成prepare
$statement = $connection->prepare($sql);
最後,在執行的地方,我們再把值放入placeholder之中:
$sn = 11; $statement->execute(array( 'sn' => $sn ));
這時候,我們一樣可以截取出sn = 11 的資料。
可是,這時候如果我們在把sn = 11 改成 sn = 11 or 1的話,將一樣只會出現sn = 11的資料,如此一來,便無法讓駭客成功獲得所有的資料。
$sn = '11 or 1'; $sql = "select * from pdo where sn = :sn"; $statement = $connection->prepare($sql); $statement->execute(array( 'sn' => $sn )); echo "<pre>"; print_r($statement->fetchALL(PDO::FETCH_ASSOC)); echo "</pre>";
另一種prepared寫法則是用?取代placeholder像這樣:
$sn = '11';
$sql = "select * from pdo where sn = ?";
$statement = $connection->prepare($sql);
$statement->execute(array($sn));
echo "<pre>";
print_r($statement->fetchALL(PDO::FETCH_ASSOC));
echo "</pre>";
在PDO中使用where in 指令
在PDO中使用Where IN 指令也不困難,假設我想要獲取sn = 8,9,11,12資料,我可以先產生一個陣列:
$sn = array(8,9,11,12);
接著,看我想要取得幾個sn,我就輸入幾次問號,語法如下:
$placeholder = implode(',', array_fill(0, count($sn), '?'));
透過同樣的方法執行
$statement = $connection->prepare("SELECT * FROM pdo WHERE sn IN ($placeholder)"); $statement->execute($sn);
最後呼叫出結果來看:
echo "<pre>"; print_r($statement->fetchALL(PDO::FETCH_ASSOC)); echo "</pre>";
就可以看到,我們只抓取出sn = 8,9,11,12的資料。
結論
這兩篇文章提供了簡單使用PDO的方法,方便完全沒有經驗的人,可以逐漸上手PDO這個物件,然而,PDO的功能非常多,這裡只是帶到最基本的皮毛而已,若有需要繼續深入的人,可以透過網路或其他的參考資料,對PDO有更多的了解。
參考資料
Site-Point:Re-introducing PDO – the Right Way to Access Databases in PHP
Site-Point:video: atabase access with php
PHP.net:PHP PDOStatement:fetch
web3.5 : PDO (PHP Data Object) 簡易教學
心情雜物間:PDO學習
Site-Point:video: atabase access with php
PHP.net:PHP PDOStatement:fetch
web3.5 : PDO (PHP Data Object) 簡易教學
心情雜物間:PDO學習
0 意見:
張貼留言