PDO参数根本不起作用

时间:2011-04-21 00:23:19

标签: php mysql sql pdo

我正在浏览一些代码并更改它的数据库部分以使用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();

有什么建议吗?

由于

2 个答案:

答案 0 :(得分:1)

将参数作为参数传递给ORDER BY子句时,它们被视为文字表达式。如果要按列或别名排序,则需要传递标识符。在MySQL中,这些由不带引号的字符串表示,或者最好是反引号引用的字符串,例如

ORDER BY `fname`

同样,方向常数(如果存在)必须使用两个关键字ASCDESC中的任意一个。我不确定如果你试图使用一个参数(将被评估为表达式)会发生什么。


以下是我过去使用允许订购列的地图的方法......

$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注入域,所以要非常小心你做的事情。