2015-07-19 43 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