2015-07-19 45 views
1

我是PHP新手,希望有人能幫助我解決這個問題。PHP:在SQL注入預防的查詢中使用IN語句時出錯

我目前有以下PHP是jQuery中Ajax調用的一部分。 手動輸入ID而不是?(例如1,2,3,4,5)然後這個按預期工作,但是當我使用下面的查詢時,它只返回一個項目,如下所示,所以我相信IN(?)的組合和我嘗試防止SQL注入在這裏不起作用。

有人能告訴我我在做什麼錯嗎?
此外,這創建了一個多維數組,我想知道這是否可以簡化,因爲我只需要每個項目的ID(tID)和值(content)。

我的PHP:

$content = implode(",", $_POST["content"]); // an array containing IDs retrieved from Ajax 
$languageFrm = $_POST["languageFrm"]; 

$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID IN(?) ORDER BY tID"); 
$stmt->bind_param("s", $content); 
$stmt->execute(); 
$result = $stmt->get_result(); 
while($arrTranslations = $result->fetch_assoc()){ 
    $translations[] = array("tID" => $arrTranslations["tID"], "content" => $arrTranslations[$languageFrm]); 
} 
var_dump($translations); 

電流導致的Ajax:

array(1) { 
    [0]=> 
    array(2) { 
    ["tID"]=> 
    int(1) 
    ["content"]=> 
    string(6) "Value1" 
    } 
} 

更新:
我的問題是,即使發佈的鏈接和電流的答案似乎請參閱適當的解決方案,因爲我無法繼續使用其他PHP代碼每當我使用其中一種建議的解決方案時,我會收到錯誤「Call to a member function fetch_assoc() on a non-object...」。

非常感謝任何幫助,
邁克

+1

請參閱:http://stackoverflow.com/q/1586587/3933332 – Rizier123

+1

使用其中一種解決方法來展開佔位符「?」,「?」,...參數綁定列表。 [MySQLi在IN中使用IN](http://stackoverflow.com/q/3269407),[我可以將數組綁定到IN()條件嗎?](http://stackoverflow.com/q/920353) ,[MySQLi準備語句與IN運算符](http://stackoverflow.com/q/11938876) – mario

+0

@ Rizier123:謝謝 - 我會看看。 – keewee279

回答

1

要綁定一個字符串到您的SQL代碼的參數。意思是你的SQL轉換爲SELECT something FROM table WHERE attribute IN ("1,2,3,4,5"),這顯然不是你想要的。

你要做的是將多個參數動態綁定到你的SQL。這可以通過在PHP manual under Example #5 of PDOStatement::execute()中演示的動態設置準備語句中的參數數量來實現。我已經在手冊中添加了這個通用示例,因爲這是一個非常常見的用例。


由於您使用的MySQLi和PDO不是在這裏,我會提供的MySQLi equivelant例子...

$params = $_POST["content"]; 

$place_holders = implode(',', array_fill(0, count($params), '?')); 


$stmt = $conn->prepare("SELECT tID, " . /* no way on earth will I ever do 
              this $languageFrm */ null . 
         " FROM TranslationsMain WHERE tID IN($place_holders) ORDER BY tID"); 
// substitute PDO::execute() for call_user_func_array to bind_params because MySQLi sucks 
call_user_func_array([$stmt, 'bind_param'], $params); 
$stmt->execute(); 
$result = $stmt->get_result(); 
while($arrTranslations = $result->fetch_assoc()){ 
    $translations[] = array(
          "tID" => $arrTranslations["tID"], 
          "content" => $arrTranslations[$languageFrm], 
          ); 
} 
var_dump($translations); 

您仍然容易受到SQL注入

請因爲您將用戶提供的輸入直接連接到您的SQL狀態中,所以還應考慮您準備好的語句容易受到SQL注入的影響$_POST["languageFrm"]在線路

$stmt = $conn->prepare("SELECT tID, " . $languageFrm . 
     " FROM TranslationsMain WHERE tID IN(?) ORDER BY tID"); 

,在你準備好的聲明中的大紅色耀眼$languageFRM是來自用戶的輸入,是你的SQL代碼的一部分,即渲染你的一切在你的查詢中使用參數沒什麼用處,這裏努力ENT。

+0

非常感謝 - 這有助於很多! – keewee279

+0

更新:我看了你的例子,並相應地更新了我的代碼,但它看起來像然後我不能使用我的代碼的其餘部分(即everystng後$ stmt-> execute();),因爲這是拋出錯誤「調用一個非對象的成員函數fetch_assoc()...「。你能讓我知道我將不得不調整嗎?另外,我不確定,但是在我看來,您可能必須用(「。$ place_holders。」)替換示例中的($ place_holders)。 – keewee279

+1

這表明'$ result'不是一個對象,進一步推斷你對'$ stmt-> get_result()'的調用失敗。請參見[MySQLiStatement :: getResult失敗時返回的內容](http://php.net/manual/en/mysqli-stmt.get-result)。注意我指出的例子是PDO,而你在這裏使用'MySQLi'。爲了使這個代碼適應MySLQi,你需要用'call_user_func_array'調用'MySQLiStatement :: bindParam()'。不,這個例子是正確的,因爲SQL字符串在準備調用中包含大括號。 – Sherif