2010-09-22 337 views
3

我傳遞一個變量來執行一個查詢功能mysql_real_escape_string的安全替代方法? (PHP)

MySQL的連接只發生在函數內部,並關閉功能

我希望能安全逃離字符串之前我裏面它們發送到功能

,因爲它需要一個MySQL連接(其只被在函數內部製造)

我知道簡單的答案是爲了躲避函數內部字符串我不能用mysql_real_escape_string,但我不能這樣做,因爲我需要發送一些逃脫了,和一個字符串

例如一些非逃出的部分,我需要運行這樣的功能:

myquery("'" . escape_me("My string") . "'"); 

通知我發送兩個apostrophe's--轉義,與逃脫的字符串裏面。出於這個原因,我不能在myquery函數內部的參數上執行一個全局的mysql_real_escape_string。

我發現下面的代碼,這意味着我可以用它來替代mysql_real_escape_string:

// escape characters 
function escape_me($value) { 
    $return = ''; 
    for($i = 0; $i < strlen($value); ++$i) { 
     $char = $value[$i]; 
     $ord = ord($char); 
     if($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126) 
      $return .= $char; 
     else 
      $return .= '\\x' . dechex($ord); 
    } 
    return $return; 
} 

我不知道這個功能是從多字節攻擊安全的,但我想我還需要撤消功能我每次查詢

例如,輸入: 測試3的「OK」變成測試3x27s x22OKx22數據庫

所以我的主要問題是: 待辦事項你知道是否有另一個函數可以作爲mysql_real_escape_string的替代函數來安全地轉義字符嗎?

+0

得到了一個非轉義的東西的例子? – 2010-09-22 16:44:45

回答

5
  • 每次你打電話給這個函數時連接都是可怕的想法。一個好的計劃應用程序不會有這種奇怪的限制。
  • 可以使用替代,這樣
    myquery("SELECT * FROM table WHERE id = %s","My string");

  • 您可以使用替代的另一種方式,一個現代化的一個:準備語句。這將在許多其他答案中描述。

因爲沒有人發佈它,這裏是粗略的例子

function fetchAll(){ 
$args = func_get_args(); 
$query = array_shift($args); 
$stmt = $pdo->prepare($query); 
$stmt->execute($args); 
return $stmt->fetchAll(); 
} 
$a=$db->fetchAll("SELECT * FROM users WHERE status=? LIMIT ?,?",$status,$start,$num); 
  • 只要你使用單字節編碼或UTF-8,無需使用mysql_real_escape_string,所以 mysql_escape_string(已棄用)或addslashes將是不夠的
+2

'mysql_escape_string'已被[棄用](http://php.net/manual/en/function.mysql-escape-string.php)(贊成'mysql_real_escape_string'),但除此之外,好東西。 +1 – NullUserException 2010-09-22 16:40:38

+0

謝謝,我忘了 – 2010-09-22 16:48:04

+0

這是有道理的,爲每個pageload連接一次比連接每個查詢要好 - 我可以在函數運行之前做一個db連接,我在做內部連接,認爲最好打開並關閉連接爲每個查詢 – samJL 2010-09-22 17:40:29

0

我會建議傳入一個值的數組進行轉義和使用sprintf()格式化查詢,同時轉義每個值。這裏是我的查詢功能的第一部分:

public function querya($query, $args=null){ 
    //check if args was passed in 
    if($args !== null){ 
     //if an array... 
     if(is_array($args)){ 
      //...escape each value in the args array 
      foreach($args as $key=>$value){ 
       $args[$key] = mysql_real_escape_string($value); 
      } 
      //add the query to the beginning of the args array 
      array_unshift($args, $query); 
      //call sprintf with the array as arguments to sprintf 
      $query = call_user_func_array("sprintf", $args); 
     } else { 
      //if args is not an array, then string (single argument passed in). 
      $query = sprintf($query, mysql_real_escape_string($args)); 
     } 
    } 

    //perform query, other stuff 
} 
+0

在類似的函數中,我將引號添加到%s通配符,就像一個萬無一失,確保查詢中沒有%s沒有引號。 – 2010-09-22 16:55:12

+0

是有道理的。這只是我自己使用的,所以我通常編寫我的查詢,如'$ DB-> querya(「SELECT COLUMN FROM TABLE WHERE VALUE ='%s'AND 1 =%d」,array('test',1)); '並在需要時在查詢中包含引號。 – 2010-09-22 17:15:14