2011-02-15 15 views
1

我工作的一個相當大的項目,其中有很多的地方,如下面的代碼存在:它真的檢查PHP中的每個數組索引有多重要?

function foo($a, $b, $c, $d, $e, $f) { 
    $clean = array(); 
    $mysql = array(); 

    $clean['a'] = htmlentities($a); 
    $clean['b'] = htmlentities($b); 
    $clean['c'] = htmlentities($c); 
    $clean['d'] = htmlentities($d); 
    //... 

    $mysql['a'] = mysql_real_escape_string($clean['a']); 
    $mysql['b'] = mysql_real_escape_string($clean['b']); 
    $mysql['c'] = mysql_real_escape_string($clean['c']); 
    $mysql['d'] = mysql_real_escape_string($clean['d']); 
    //... 

    //construct and execute an SQL query using the data in $mysql 
    $query = "INSERT INTO a_table 
       SET a='{$mysql['a']}', 
        b='{$mysql['b']}', 
        c='{$mysql['c']}', 
        d='{$mysql['d']}'"; 
} 

顯然,這引發了很多警告在PHP中未定義的指標。

是否真的有必要重寫代碼如下?

function foo($a, $b, $c, $d, $e, $f) { 
    $clean = array(); 
    $mysql = array(); 

    $clean['a'] = htmlentities($a); 
    $clean['b'] = htmlentities($b); 
    $clean['c'] = htmlentities($c); 
    $clean['d'] = htmlentities($d); 
    //... 

    $mysql['a'] = (isset($clean['a'])) ? mysql_real_escape_string($clean['a']) : mysql_real_escape_string($a); 
    $mysql['b'] = (isset($clean['b'])) ? mysql_real_escape_string($clean['b']) : mysql_real_escape_string($b); 
    $mysql['c'] = (isset($clean['c'])) ? mysql_real_escape_string($clean['c']) : mysql_real_escape_string($c); 
    $mysql['d'] = (isset($clean['d'])) ? mysql_real_escape_string($clean['d']) : mysql_real_escape_string($d); 
    //... 

    //construct and execute an SQL query using the data in $mysql 
    if (isset($mysql['a']) and isset($mysql['b']) and isset($mysql['c']) and isset($mysql['d'])) { 
     $query = "INSERT INTO a_table 
        SET a='{$mysql['a']}', 
         b='{$mysql['b']}', 
         c='{$mysql['c']}', 
         d='{$mysql['d']}'"; 
    } 

} 
+1

那麼,如果你真的設置每個'$ clean ['something']`,那麼你就不應該得到通知。順便說一句,你有很多重複。考慮使用循環或`array_map`:http://php.net/manual/en/function.array-map.php – 2011-02-15 17:03:23

回答

1

您可以簡化您的功能,如果你用了很多:

function foo($a, $b, $c, $d, $e, $f) { 

    $args = func_get_args(); // or build an array() manually 

    $args = array_map("htmlentities", $args); 
    $args = array_map("mysql_real_escape_string", $args); 

    list($a, $b, $c, $d, $e, $f) = $args; 

的isset()函數的顯示位置檢查似乎完全無用。變量已經定義。

1

是否有必要擁有這樣一個硬編碼的函數?

我使用此:

function insert_array($table, $data) { 
    $cols = '('; 
    $values = '('; 
    foreach ($data as $key=>$value) { 
     $value = mysql_real_escape_string($value); 
     $cols .= "$key,"; 
     $values .= "'$value',"; 
    } 
    $cols = rtrim($cols, ',').')'; 
    $values = rtrim($values, ',').')'; 
    $sql = "INSERT INTO $table $cols VALUES $values"; 
    mysql_query($sql) or die(mysql_error()); 
} 

然後插入數據,而不管其名稱和列使用:

$data = array('id' => 1, 'name' => 'Bob', 'url' => 'foo.com'); 
insert_array('users', $data); 
+0

+1 OMG !!我從來沒有這樣想過,非常有幫助,謝謝。 – enam 2011-02-15 17:13:00

+0

有用的想法,但不是在這種情況下 - 爲了簡單起見,我刪除了我們通常執行的其他數據操作。所有的函數參數都不一定與表格列匹配。 – Jon 2011-02-15 17:20:49

1

是,如果陣列索引或變量不存在的PHP給予警告/注意。

正確的方法是檢查每個變量,然後使用它們與isset()函數。

這是一個很好的做法,在使用前檢查它們。

+0

不是這種情況下,所有`$ a,$ b,$ c,$ d`都是定義的函數參數 – ajreal 2011-02-15 17:10:27

0

您需要檢查可能存在或不存在的索引。但是,您的代碼非常混亂,您的真實代碼看起來可能完全不同。在這個示例代碼中,鍵明顯存在,您只是自己創建它們。

  1. 在你的榜樣,你可以移動mysql_real_escape_string部內的,如果在您檢查變量,那麼你已經知道它們的存在。

  2. 這裏沒有理由使用數組,您可以將它們存儲在同一個變量中。

  3. XSS-Protection(htmltentities(),注意這還不夠)應該在分散數據之前完成,而不是在存儲之前完成。只有一個原因是你最終會得到多次編碼/轉義的東西。惡意的HTML/JS在你的數據庫中不會造成任何傷害。

0

如果你的項目是非常大的,那麼不確定的指標可以成爲一個噩夢的路線,特別是如果他們持有由用戶輸入產生的數據,尤其是在沒有良好的錯誤與堆棧跟蹤報告。這是因爲在請求之間傳遞數據時,不能保證它被設置在它的原始入口點,因此最終會對空值或空值進行大量冗餘檢查。

您可能想要檢查一下,如果您在此嘗試完成的任務可能無法通過將此功能變爲對象來實現。用$ a $ b和$ c表示的值可以很容易地變成對象屬性,一個save()方法可以將狀態保存到數據庫中。

除此之外,您可以通過使用foreach循環更快速和更連貫地執行檢查。只需通過鍵遍歷數據並在循環體內執行真正的轉義和htmlentities。

http://php.net/manual/en/control-structures.foreach.php

我也建議HTMLPurifier你的XSS過濾功能,很多時候htmlentites是insufficent,特別是對於那些接受用戶的內容被放置在Web應用程序中的公共形式。

http://htmlpurifier.org/