在获取所有安全性结果时,是否需要绑定结果?

时间:2014-01-02 17:30:58

标签: php sql sql-injection sqlbindparameter

我对MySQL很新,所以如果这听起来像个愚蠢的问题,我很抱歉。

当我学习sql安全性并防止sql注入时,我了解到在获取像这样的id的结果时使用bindparam会更好:

//Prepare Statement
$stmt = $mysqli->prepare("SELECT * FROM my_table WHERE id=?");

if ( false===$stmt ) {
  die('prepare() failed: ' . htmlspecialchars($mysqli->error));
}

$rc = $stmt->bind_param("i", $id);

if ( false===$rc ) {
  die('bind_param() failed: ' . htmlspecialchars($stmt->error));
}

$rc = $stmt->execute();

if ( false===$rc ) {
  die('execute() failed: ' . htmlspecialchars($stmt->error));
}


// Get the data result from the query. You need to bind results for each column that is called in the prepare statement above
$stmt->bind_result($col1, $col2, $col3, $col4);

/* fetch values and store them to each variables */
while ($stmt->fetch()) {
   $id = $col1;
   $abc = $col2; 
   $def = $col3; 
   $xyz = $col4;
}

$stmt->close();

$mysqli->close();

Atm,当我拿到所有结果时,我正在使用它:

$query= "SELECT * FROM my_table";  
$result=mysqli_query($connect, $query);

if (!$result)  
{  
  die('Error fetching results: ' . mysqli_error()); 
  exit();  
}

echo '<table border="1">'; // start a table tag in the HTML
//Storing the results in an Array
while ($row = mysqli_fetch_array($result))  //Creates a loop to loop through results
{  
    echo "<tr><td>" . $row['abc'] . "</td><td>" . $row['def'] . "</td><td>" . $row['xyz'] . "</td></tr>";  
}  
echo '</table>'; //Close the table in HTML

我的问题是:

1)对于我的第二个代码,出于与我的第一个示例类似的任何安全原因,我是否需要在获取所有结果时使用bind_result

2)如果是,当我获取所有结果而不使用bind_result时,如何使用$id准备语句?

3)如果我按照获取所有结果的方式使用第二个示例,是否存在任何安全问题?

请你帮我理解这个......

1 个答案:

答案 0 :(得分:4)

  

1)对于我的第二个代码,出于与我的第一个示例相似的任何安全原因,我是否需要在获取所有结果时使用bind_result?

没有。 bind_result()与安全无关。您可以对任何查询使用任何方法。

  

2)如果是,当我获取所有结果而不是使用$ id时,如何在bind_result中使用prepare语句?

与任何其他查询完全相同。实际上没有区别。并且任何特定的变量根本不重要。

  

3)如果我按照获取所有结果的方式使用第二个示例,是否存在任何安全问题?

始终存在安全问题。但是在这个片段中没有来自SQL注入的区域。您可能希望检查XSS问题。

只是为了澄清你的含糊问题:
如果您将bind_resultbind_param混淆,这是一条经验法则:您必须对要进入查询的每个变量使用占位符(以及bind_param())。 总是。没有例外。

根据此规则,您可以简单地告诉您是否需要在任何特定情况下使用prepare()

此外,在第一个例子中不需要这么长且有风的代码。

$stmt = $mysqli->prepare("SELECT * FROM my_table WHERE id=?");
$rc = $stmt->bind_param("i", $id);
$rc = $stmt->execute();
$stmt->bind_result($id, $abc, $def, $xyz);
while ($stmt->fetch()) {
  echo $id;
}

在连接之前,只需在异常模式下设置mysqli:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);