PHP | MySQLi预处理语句 - 处理order by和order类型参数

时间:2016-11-05 19:29:27

标签: php mysql mysqli prepared-statement sql-injection

为了避免SQL注入我做了一些研究并基于this回答我开始使用MySQLi准备好的状态。这一切都很顺利,直到我根据用户点击的内容进入从前端发送的order byorder type参数。更具体地说,我有一些带有一些标题的表格,用户可以根据名称,价格,日期等安排数据,也可以在ASCDESC之间进行选择。我把它存储到一些隐藏的输入类型中,所以我猜他们可以使用firebug来改变它。因此,我需要确保他们不能将任何内容注入我的数据库。

$stmt = $dbConnection->prepare('SELECT * FROM mytable WHERE 1 ORDER BY ? ?');
$stmt->bind_param('ss', $_GET['order_by'], $_GET['order_type']);

似乎我收到了错误。我做了一些研究,有人说没有解决方案,另一个人说唯一的解决方案是硬编码而另一个人说我必须退出使用准备好的语句并尝试mysql_real_escape_string但是在我链接的答案中有人说:

  

如果您使用的是最新版本的PHP,则为mysql_real_escape_string   下面列出的选项将不再可用

所以我猜这也不是这样的。所以我的问题仍然是,接下来我该怎么办?这个问题有解决方案吗?

2 个答案:

答案 0 :(得分:3)

您不能将参数用于列名,仅用于值。只需检查列名是否有效。

$allowed_order_by = array('col1', 'col2', 'col3', ...);
$allowed_order_type = array('asc', 'desc', '');
if (in_array(strtolower($_GET['order_by']), $allowed_order_by) &&
    in_array(strtolower($_GET['order_type'], $allowed_order_type)) {
    $stmt = $dbConnection->prepare("
        SELECT * FROM mytable 
        ORDER BY {$_GET['order_by']} {$_GET['order_type']}");
    $stmt->execute();
}

答案 1 :(得分:1)

SQL不允许列别名,表达式或关键字的参数。您需要将它们直接插入查询中:

$stmt = $dbConnection->prepare('SELECT * FROM mytable WHERE 1 ORDER BY '.$_GET['order_by'].' '.$_GET['order_type');

如果这些是由用户提供的,则应在将它们放入查询字符串之前对其进行验证。