2013-11-02 38 views
1

我有一個頁面將不同的參數附加到用於查詢的URL。SQL注入 - 這個查詢是否安全?

例如

http://www.example.com/search.php?category=Schools&country[]=Belgium&country[]=Czech+Republic 

我的代碼是這樣的

if(isset($_GET['country'])){ 
$cties = "'" . implode("','", $_GET['country']) . "'"; 
} 
else { 
$cties = "'Albania','Andorra','Austria','Belarus','Belgium','Bosnia & Herzegovina','Bulgaria','Croatia','Czech Republic','Denmark','Estonia','Faroe Islands','Finland','France','Germany','Gibraltar','Great Britain','Greece','Hungary','Iceland','Ireland','Isle of Man','Italy','Latvia','Liechtenstein','Lithuania','Luxembourg','Macedonia','Malta','Moldova','Monaco','Montenegro','Netherlands','Norway','Poland','Portugal','Serbia','Romania','San Marino','Slovakia','Slovenia','Spain','Sweden','Switzerland','Ukraine','United Kingdom'";   
} 
if(isset($_GET['category'])){ 
$cat = $_GET['category']; 
} 
else{ 
$cat = " "; 
} 

try{ 
// create the Prepared Statement 

$stmt = $con->prepare("SELECT * FROM MyTable 
WHERE MyDate >= DATE(NOW()) 
AND (Category=:cat or '' = :cat) 
AND Country IN ($cties) 
ORDER BY MyDate ASC"); 
$stmt->bindValue(':cat', $cat, PDO::PARAM_STR); 
$stmt->execute(); 

我在想,如果這個查詢是安全的,如果不是,我在做什麼錯。 在此先感謝!

我終於得到它(感謝你的常識):

if(isset($_GET['country'])){ 
$arr = $_GET['country']; 
} 
else {   
$arr = array('Albania','Andorra','Austria','Belarus','Belgium','Bosnia & Herzegovina','Bulgaria','Croatia','Czech Republic','Denmark','Estonia','Faroe Islands','Finland','France','Germany','Gibraltar','Great Britain','Greece','Hungary','Iceland','Ireland','Isle of Man','Italy','Latvia','Liechtenstein','Lithuania','Luxembourg','Macedonia','Malta','Moldova','Monaco','Montenegro','Netherlands','Norway','Poland','Portugal','Serbia','Romania','San Marino','Slovakia','Slovenia','Spain','Sweden','Switzerland','Ukraine','United Kingdom'); 
} 
if(isset($_GET['category'])){ 
$cat = $_GET['category']; 
} 
else{ 
$cat = " "; 
} 
// create the Prepared Statement 
$in = str_repeat('?,', count($arr) - 1) . '?'; 

$sql = "SELECT * FROM MyTable WHERE MyDate >= DATE(NOW()) 
    AND Country IN ($in) 
    AND (Category=? or '' = ?) 
    ORDER BY MyDate ASC"; 
$stmt = $con->prepare($sql); 
$arr[] = $cat; // adding category to array 
$arr[] = $cat; // we need it twice here 
// finally - execute 
$stmt->execute($arr); 
+4

http://stackoverflow.com/a/15991146/285587 –

+0

@YourCommonSense謝謝!你介意看看我的編輯?這是否解決了這個問題? – user1204121

+0

沒有。它沒有任何意義。你應該在查詢中只添加**佔位符**,但從來沒有像你這樣的實際數據。 –

回答

2

是啊,現在我明白你的問題。那麼,對於這樣的任務,PDO並不是太方便的庫。所以,首先我會告訴你如何將它與我自己的庫來完成:

$sql = "SELECT * FROM MyTable WHERE MyDate >= CURDATE() 
      AND (Category=?s or '' = ?s) 
      AND Country IN (?a) 
      ORDER BY MyDate ASC" 
$data = $db->getAll($sql, $cat, $cat, $_GET['country']); 

但我很明白,大家這麼傾向於熟悉的方法。那麼,讓我們詳細描述醜陋的PDO

首先,目標是什麼?目標是

  1. 創建包含所有數據佔位符的查詢。我會堅持位置佔位符,因爲它們更容易實現。
  2. 要與所有具有綁定到佔位符

看來,我們需要兩個佔位符類別和一些未知數量的城市來回的變量創建一個數組。好的,這一行將創建一串佔位符:

$in = str_repeat('?,', count($arr) - 1) . '?'; 

我們將插入到查詢中。

// $arr is array with all the vars to bind. at the moment it contains cities only 
$arr = $_GET['country']; 
// creating string of ?s 
$in = str_repeat('?,', count($arr) - 1) . '?'; 
// building query 
$sql = "SELECT * FROM MyTable WHERE MyDate >= DATE(NOW()) 
       AND Country IN ($in) 
       AND (Category=? or '' = ?) 
       ORDER BY MyDate ASC"; 
$stm = $db->prepare($sql); 
$arr[] = $_GET['category']; // adding category to array 
$arr[] = $_GET['category']; // we need it twice here 
// finally - execute 
$stm->execute($arr); 
$data = $stm->fetchAll(); 
+0

非常感謝!現在我越來越近了。唯一沒有工作的是當類別爲空時。但我會解決這個問題:-)一旦找到解決方案,即刻更新我的帖子。 – user1204121

+0

非常感謝!它現在有效。但是,你能解釋一下爲什麼我必須兩次添加類別嗎? – user1204121

+0

因爲您在qwuery中有兩次類別 –