我正在浏览一些代码并更改它的数据库部分以使用PDO。到目前为止,除了我准备好的声明中的参数外,一切都运行正常。由于某种原因,下面的代码根本不起作用。两个$ _GET变量基本上用于特定页面上的排序目的。查询本身在不使用参数的情况下工作正常,如果我手动将“ORDER BY id DESC”放在最后,那也可以正常工作。我似乎无法使用变量参数。这是代码:
$sort = $_GET['sort'];
$order = $_GET['order'];
$statement = $db->prepare('SELECT uid, id, fname, lname, ext, uname
, email, access, created, modified, last_login, enabled
FROM users
ORDER BY :col :or');
$statement->bindParam(':col', $sort);
$statement->bindParam(':or', $order);
$statement->execute();
$num = $statement->rowCount();
有什么建议吗?
由于
答案 0 :(得分:1)
将参数作为参数传递给ORDER BY
子句时,它们被视为文字表达式。如果要按列或别名排序,则需要传递标识符。在MySQL中,这些由不带引号的字符串表示,或者最好是反引号引用的字符串,例如
ORDER BY `fname`
同样,方向常数(如果存在)必须使用两个关键字ASC
或DESC
中的任意一个。我不确定如果你试图使用一个参数(将被评估为表达式)会发生什么。
以下是我过去使用允许订购列的地图的方法......
$orderCols = array(
'firstName' => 'fname',
'lastName' => 'lname'
);
$sort = isset($_GET['sort'], $orderCols[$_GET['sort']])
? $orderCols[$_GET['sort']
: 'uid'; // some sane default
$order = isset($_GET['order']) && $_GET['order'] == 'DESC'
? 'DESC' : 'ASC';
$query = sprintf('SELECT uid, id, fname, lname, ext, uname, email, access, created, modified, last_login, enabled FROM users ORDER BY `%s` %s',
$sort, $order);
$statement = $db->prepare($query);
答案 1 :(得分:0)
使用参数作为伪关键字将无法正常工作! 这是(部分)使用参数防止SQL注入攻击的原因。
当然,因为您可以操纵字符串,所以您只需插入“DESC' /' ASC'在那里,重新打开整个SQL注入漏洞。
因此:col 不被接受为字段。关于$ order我会建议像
这样的代码伪代码(不是真正的php)
if uppercase($order) <> 'DESC' then $order = 'ASC';
$query = 'select ... '+ $order;
显式测试将任何注入代码转换回ASC&#39;这样可以安全地破解它。
当然,对于该字段,您还可以对所有可能的字段名称进行显式测试。只要你确定可能的结果只能是有效字段名称,那么你就是好的,但它正在勉强执掌。
警告强>
既然你(可能)回到操作查询字符串,你也会回到SQL注入域,所以要非常小心你做的事情。