2016-11-05 99 views
0

为了避免SQL注入,我做了一些研究并基于this答案我开始使用MySQLi编写的statemets。这一切都很顺利,直到我根据用户点击的内容从前端发送的参数order byorder type。为了更具体一些,我有一些表和一些标题,用户可以安排数据考虑名称,价格,日期等,他也可以选择ASCDESC。我将它存储到一些隐藏的输入类型中,所以我猜想他们可能会使用firebug来更改它。正因为如此,我需要确保他们不能将任何东西注入到我的数据库中。PHP | MySQLi准备的语句 - 处理顺序和顺序类型参数

$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 选项将不再可用

所以我gueess这是不是也是这样。所以我的问题仍然存在,接下来我应该做什么?有这个问题的解决方案吗?

+0

您只能使用参数的值,您不能用它们来替换表和列的名称。 – Barmar

+0

'mysql_real_escape_string'不可用的原因是因为'mysql'扩展名不见了。但是如果你使用'mysqli',它有'mysqli_real_escape_string'。但这对此没有用处,因为它用于转义字符串而不是列名。 – Barmar

回答

1

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

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

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

+0

如果我必须自己验证他们,为什么我应该使用准备好的statemets? ..因为他们不处理这个,而不是我? – paulalexandru

+1

@paulalexandru如果查询有其他参数,则使用准备好的语句。 – Barmar

+0

@Barmar - 为什么其他参数?为什么不是所有的参数?这个参数来自用户端,他可以编辑它们,如果他想要的话。 – paulalexandru

2

不能使用列名称的参数,只能使用值。只需检查列名是否有效。

$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(); 
} 
+0

'$ _GET ['order_ty [e]'正在抛出语法突出显示。你可能意思是'$ _GET ['order_type']' –

+0

@ Fred-ii-随意编辑这样的明显的拼写错误 – Barmar

+0

我只有TBH,并不完全确定可能是另一个数组。 –