2010-07-14 52 views
3

可能重複:
mysql_fetch_array() expects parameter 1 to be resource, boolean given in selectPHP初學者安全輸入

我在這裏需要一些幫助。

我有這個疑問:

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title'; 
$query = mysql_query("SELECT * FROM entry ORDER BY $order ASC"); 

您可以通過標題,日期或作者秩序。

但是,如果有人向$爲了別的東西有云:

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\wamp\www\entries.php on line 20 

如何擺脫這種錯誤信息的?

感謝

回答

2

您不應該將列標識符與字符串文字相同。在你的例子中,你可能會得到像這樣的SQL:

SELECT * FROM entry ORDER BY O\'Hare ASC 

這將導致任何SQL解析器中的語法錯誤。

我有幾個建議:

  1. 把你的SQL到一個變量,不要試圖調用內部建立它mysql_query()。如果你使用一個變量,你現在可以檢查SQL字符串,這使得上面的錯誤更容易理解。

    $sql = "SELECT * FROM entry ORDER BY $order ASC"; 
    // here you can log $sql, or output to Firebug, etc. 
    $query = mysql_query($sql); 
    
  2. 檢查返回值是否表示錯誤。您需要檢查錯誤狀態,因爲它們可能會出於多種原因。

    $query = mysql_query($sql); 
    if ($query === false) { 
        die(mysql_error()); 
    } 
    
  3. 使用mysql_real_escape_string()字符串 - 不是列名,表名,SQL關鍵字等我改用是一個關聯數組,該輸入有效的列名$_GET映射,所以我知道它是安全的。這也允許您在應用參數中使用不同於列名稱的值。

    $ordercolumns = array(
        "t" => "title", 
        "d" => "date" 
    ); 
    $order = "title"; // the default 
    if (isset($_GET["order"]) && isset($ordercolumns[$_GET["order"]])) { 
        $order = $ordercolumns[$_GET["order"]]; 
    } 
    // now we know $order can only be 'title' or 'date', 
    // so there's no need to escape it. 
    $sql = "SELECT * FROM entry ORDER BY $order ASC"; 
    
+0

很好的答案!我學到了一些新的東西:)我將這個書籤; P – Jolabero 2010-07-14 16:18:19

0

,預計$順序列名,如果不是的話,會失敗。嘗試回顯$查詢。

0

您應該從可能的可接受值列表中檢查$ _GET ['order']的值。

在嘗試讀取行之前,您還應該檢查if($ query)以確定查詢是否有效。

1

只是不提供任何訂單選項的用戶,那不。如果您正在使用文本輸入,請將其替換爲select。只要該列存在,就不應該出現錯誤。

你可能會硬編碼每個選項的開關情況:

switch($_GET['order']){ 
    case 'date' : 
     $order = 'date'; 
     break; 
    case 'author' : 
     $order = 'author'; 
     break; 
    default 
     $order = 'title'; 
} 

這也將防止SQL-注射。

6

您不能在order by子句中使用類似colu\'nname的東西 - 這意味着mysql_real_escape_string不是此處的解決方案。

相反,您應該檢查$order實際上是否包含表格的某一列的名稱 - 如果沒有,則不運行該查詢。


例如,你可以使用這樣的事情:

if (!in_array($_GET['order'], array('column1', 'title', 'id', 'other_column'))) { 
    // deal with the problem 
    // and don't run the query 
    // because $_GET['order'] is not one of the allowed values 
} 
0
$checker = array('title', 'date', 'author') 

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title'; 

if (in_array($_GET['order'], $checker) { 
    $query = mysql_query("SELECT * FROM entry ORDER BY $order ASC"); 
} 
0

您應該檢查有效的值,如果事情是不是你希望呈現錯誤給用戶。

一個簡單的例子,

$valid_values = array("title", "date", "author"); 

if (in_array($_GET['order'], $valid_values)) 
{ 
    // Your db stuff 
} 
else 
{ 
    echo "The order value you gave wasn't valid. Please try another."; 
} 
0

您還需要確保$_GET["order"]包含一個有效的列。
您的問題來自獲取無效的列名稱,您在查詢中。 mysql_query()函數錯誤返回false,並且您的錯誤消息告訴您將它傳遞給mysql_fetch_assoc調用。

嘗試像

$columns = array("id", "name", "title"); 
if (false === ($key = array_search($_GET["column"], $columns))) { 
    $column = "title"; 
} else { 
    $column = $columns[$key]; 
} 
$query = "SELECT * FROM entry ORDER BY {$column};"; 

我沒有使用mysql_real_escape_string,因爲這種方法也檢查輸入的是在有效選項列表。

0

檢查看$順序運行查詢

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title'; 
//Run a check here, before the query 
$query = mysql_query("SELECT * FROM entry ORDER BY $order ASC"); 

的mysql_real_escape_string也看起來是在一個不正確的位置之前,列名。只是擡頭

+0

此代碼不會做任何檢查,如果列名是有效的... – 2010-07-14 16:13:51

+0

我只是顯示OP那裏做檢查。在你設置var之後,在你嘗試查詢之前...... – 2010-07-14 16:32:05