2013-03-11 56 views
1

我一直在爲視頻網站開發一個項目。它從數據庫中提取信息並在需要的地方插入細節。PDO實現,MySQL,SQL注入

到目前爲止,一切都很完美,但我剛剛完成了SQL注入測試,並且所有內容都完全打開。我一直在尋找答案來關閉它,並使事情變得更加安全。

我試圖實現PDO的聲明,但我不能得到我的頭。我只在本月爲php/sql工作,所以我非常新。

任何幫助或其他的解決方案將是驚人的,下面的代碼是我的,我相信主要頁面的連接點,也是最脆弱的部分

<?php 
$username="********"; 
$password="*******"; 
$database="*******"; 

$id = $_GET['id']; 
$badchars = array("\"", "\\", "/", "*", "'", "=", "-", "#", ";", "<", ">", "+", "%"); 
$myid = str_replace($badchars, "", $id); 
mysql_connect('localhost',$username,$password); 
@mysql_select_db($database) or die("Unable to select database"); 
$result = mysql_query("SELECT * FROM Videos WHERE id='$id'"); 
while($row = mysql_fetch_array($result)) { 
    $title=mysql_result($result,0,"title"); 
    $url=mysql_result($result,0,"url"); 
    $id=mysql_result($result,0,"id"); 
    $description=mysql_result($result,0,"description"); 
    $source=mysql_result($result,0,"source"); 
    $type=mysql_result($result,0,'type'); 
} 
?> 
+3

***不要試圖讓你自己的SQL更清潔,使用提供給你的。 'mysql_real_escape_string'。 – 2013-03-11 19:44:24

+1

您嘗試過的PDO代碼是什麼? – 2013-03-11 19:45:52

+0

'mysql_fetch_array'給你所有的字段,你不需要使用'mysql_result' *也*。 – 2013-03-11 19:49:51

回答

2

下面是您的示例重寫爲使用PDO和解釋。

<?php 
$username="********"; 
$password="*******"; 
$database="*******"; 

try { 
    $pdo = new PDO("mysql:host=localhost;dbname=$database", $username, $password); 
} catch (PDOException $e) { 
    error_log("PDO connection error: " . $e->getMessage()); 
    header("Location: http://www.example.com/error.php"); 
    exit; 
} 

您可以將GET參數強制轉換爲int,該參數只會使用數字部分並剝離其他任何東西。

$id = (int) $_GET['id']; 

在要替換動態值的查詢中留下一個佔位符。您可以使用位置參數與?符號,或命名參數與冒號前綴語法。

$sql = "SELECT * FROM Videos WHERE id = :id"; 

在每次調用prepare()或execute()後測試錯誤都很重要。

如果錯誤不是簡單的die(),最好讓瀏覽器保持白屏,但如果可能的話應該恢復,否則至少會顯示一個友好的「哎呀!」。頁面,以便用戶可以繼續使用您的網站。

$stmt = $pdo->prepare($sql); 
if ($stmt === false) { 
    $err = $pdo->errorInfo(); 
    error_log("PDO prepare error: " . $err[2]); 
    header("Location: http://www.example.com/error.php"); 
    exit; 
} 

傳遞一個參數值數組以替代execute()的參數。在命名參數的情況下,它是一個關聯數組。在位置參數的情況下,使用簡單的序數組。

if ($stmt->execute(array(":id"=>$id)) === false) { 
    $err = $stmt->errorInfo(); 
    error_log("PDO execute error: " . $err[2]); 
    header("Location: http://www.example.com/error.php"); 
    exit; 
} 

然後你可以從語句的結果集讀取每行關聯數組:

while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
    extract($row); 
} 

注意我發現使用extract(),這是一個創建變量$冠軍的PHP內置函數,$ url等等,基於關聯數組$ row的鍵。但我這樣做只是爲了匹配你的代碼;通常我只是將這些字段引用爲$row["title"]等等。

+0

OP的注意事項:所有'try..catch'和'$ stmt-> errorInfo()'塊這裏沒用,使代碼臃腫,沒有理由沒用。在真實項目中使用此代碼時,請將其全部清除。 – 2013-03-11 20:58:35

+0

@YourCommonSense,張貼您自己的答案,因爲切線設計問題而投票下達別人的是輕率和粗魯的。 – 2013-03-11 21:00:38

+0

感謝您抽出時間回答問題,並對每個部分給出了非常詳細的解釋,正是我所需要的 當我回到筆記本電腦時,我會嘗試一下,希望我可以把它放在頭上。 不好意思,但是,可悲的是我無法對此投票,因爲我需要+15的聲望才能這樣做 – Stewart 2013-03-11 21:10:33

-1
$result = mysql_query("SELECT * FROM Videos WHERE id='" . mysql_real_escape_string($_GET['id']) . "'"); 

...你可能還需要考慮使用mysql_fetch_assoc()而不是mysql_fetch_array(),這將大大簡化結果值。那些對mysql_result()的調用根本不需要。