2013-03-13 115 views
2
function Query() 
{ 
    $args = func_get_args(); 

    if (sizeof ($args) > 0) 
    { 
     $query = $args[0]; 

     for ($i = 1; $i < sizeof ($args); $i++) 
       $query = preg_replace ("/\?/", "'" . mysql_real_escape_string ($args[$i]) . "'", $query, 1); 
    } 
    else 
    { 
      return FALSE; 
    } 

我有這樣的功能。基本上,我做出這樣的查詢:mysql(i)_real_escape_string,安全依賴?

$this->Query('SELECT * FROM USERS WHERE Username = ? AND Points < ?', $username, $points); 

它目前支持棄用mysql功能,但適應mysqli會在我的類mysqli更換mysql一樣簡單。

這是一個安全的方法來依靠對SQL注入攻擊?每個問號都被mysql_real_escape_string自動消毒,我從來沒有遇到過問題,但是我應該使用mysqli_real_escape_string進行消毒?

我知道的mysqli的預處理語句,但使用bindParam每個變量似乎有點矯枉過正了我。

您認爲如何?

+4

*「似乎有點矯枉過正」?* *「矯枉過正」有一個簡單,可靠,難以搞砸的機制來確保查詢語法的有效性並防止SQL注入? – deceze 2013-03-13 15:55:43

+0

*「,但對每個變量使用'bindParam'似乎對我有點矯枉過正」*什麼?真的嗎?這從來沒有矯枉過正。 – 2013-03-13 15:55:48

+1

不能依賴mysql_real_escape_string(可以在不依賴嵌入字符串的情況下執行「小型桌面表」);準備好的語句可能看起來過分了......直到數據庫被入侵的地步 – 2013-03-13 15:55:54

回答

1

一個真正偉大的一天 - 第二好的嘗試建立一排一個合理的數據庫抽象層。

我應該使用mysqli_real_escape_string進行消毒嗎?

沒有。
只因爲此功能不消毒任何東西。

轉換爲格式 SQL字符串文字這個函數是必須的,無法避免或替換。
所以,你正在正確使用這個功能,格式化字符串只有並格式化它們無條件
所以,你有你的疑問完全安全,只要你可以使用?標記來替換實際數據(並且 - 甚至可以讓挑剔的投訴空閒 - 只要您使用mysql(i)_set_charset()函數設置SQL編碼)。

如果有人致電您的方法 - 只是要求他們證明代碼的完整片段顯示一定的脆弱性。

但是,請讓我將您的注意力放在一些重要的事情上。

  1. 動態SQL查詢零件僅限於字符串。例如,這兩個查詢將不會與您的功能一起使用:

    SELECT * FROM table LIMIT ?,? 
    SELECT * FROM table ORDER BY ? 
    

    只是因爲數字和標識符要求不同的格式。
    所以,最好使用類型暗示佔位符,告訴你的功能,適用

  2. 要運行一個查詢只是工作的一部分的格式。你也需要得到結果。爲什麼不讓他們已經,而不用不必要的電話膨脹你的代碼?
  3. 應該有一種方法來插入文字?標記爲查詢而不解析它們。

請看看my class,它建立在與您的原理完全相同的原則上,但是我在上面提到了一些改進。我希望你會發現它有用或至少值得借鑑一兩個想法。

+0

好的。我閱讀你的回覆,但無法理解一些部分,所以如果你能再次回覆,我會很感激。一個。 mysqli_real_escape_string()不會淨化任何東西。爲什麼?它不能保證我傳遞的參數是什麼? 1.使用LIMITS進行查詢是可行的,因爲我可以發送兩個整數參數。 (我相信我經常在我的函數中使用限制。)2.我使用mysql_row_assoc得到結果,但是我將它們從這個函數中刪除,因爲它們是無關的。 3。你的意思是我應該找到一種方法來跳過參數中的合法問號? – 2013-03-13 21:26:18

+0

由於某種原因,我昨天錯過了你的評論,但在這裏你走了。一個。 http://stackoverflow.com/a/9296858/ 1.用現在的代碼它沒有。也許你有另一種情況 - 那麼是的。 2.很好,但我希望你不要自動化返回的類型3.不是在參數中,而是在查詢中。這不是什麼大問題。如果你發佈整個代碼,我會非常感激 - 所以,我不需要任何假設。 – 2013-03-14 10:40:20

+0

所以,一個。我的方法是安全的,沒有注射問題? 1.你的意思是什麼?整數,?字符串,?標識符而不是?所以他們都得到不同的處理? 3.如果有辦法與你聯繫,我可以寄給你我寫的全班。您不僅可以看到整個功能,但是如果專家會評論我的課程,我會很感激。 PS。順便說一句,謝謝你。你已經像我所有的stackoverflow問題一樣回答了很多答案。對此,我真的非常感激。 – 2013-03-14 11:59:06

2

使用綁定的參數是矯枉過正,並應符合規定。它會更有效地逃脫並準備好你的參數。

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); 
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent); 

$code = 'DEU'; 
$language = 'Bavarian'; 
$official = "F"; 
$percent = 11.2; 

/* execute prepared statement */ 
mysqli_stmt_execute($stmt); 

這是否真的看起來矯枉過正?

Documentation

+0

當然可以。它需要7行代碼,而OP需要** 1 **。對十幾個領域來說,它將是二十個,但對於OP來說仍然是一個。 – 2013-03-13 19:36:48

0

,如果你現在使用的mysqli爲mysql。最好使用mysqli_real_escape_string。 請注意參數順序已被修改。 (%和_仍然沒有逃脫)今天