为了避免SQL注入我做了一些研究并基于this回答我开始使用MySQLi准备好的状态。这一切都很顺利,直到我根据用户点击的内容进入从前端发送的order by
和order type
参数。更具体地说,我有一些带有一些标题的表格,用户可以根据名称,价格,日期等安排数据,也可以在ASC
或DESC
之间进行选择。我把它存储到一些隐藏的输入类型中,所以我猜他们可以使用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 下面列出的选项将不再可用
所以我猜这也不是这样的。所以我的问题仍然是,接下来我该怎么办?这个问题有解决方案吗?
答案 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');
如果这些是由用户提供的,则应在将它们放入查询字符串之前对其进行验证。