Php PDO参数根本不起作用

Php PDO参数根本不起作用,php,mysql,sql,pdo,Php,Mysql,Sql,Pdo,我正在浏览一些代码,并将其中的数据库部分更改为使用PDO。到目前为止,除了我准备好的声明中的参数外,一切正常。出于某种原因,下面的代码根本不起作用。两个$u GET变量基本上用于特定页面上的排序目的。查询本身在不使用参数的情况下可以正常工作,如果我手动将“orderbyiddesc”放在末尾,也可以正常工作。我似乎无法让它与可变参数一起工作。代码如下: $sort = $_GET['sort']; $order = $_GET['order']; $statement = $db->pre

我正在浏览一些代码,并将其中的数据库部分更改为使用PDO。到目前为止,除了我准备好的声明中的参数外,一切正常。出于某种原因,下面的代码根本不起作用。两个$u GET变量基本上用于特定页面上的排序目的。查询本身在不使用参数的情况下可以正常工作,如果我手动将“orderbyiddesc”放在末尾,也可以正常工作。我似乎无法让它与可变参数一起工作。代码如下:

$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();
有什么建议吗


感谢

当将参数作为参数传递给
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);

使用参数作为伪关键字显然是行不通的
这就是为什么使用参数可以防止SQL注入攻击的部分原因

当然,因为可以操作字符串,所以可以在其中插入'DESC'/'ASC',重新打开整个SQL注入孔

因此:col将而不是被接受为字段。至于$order,我推荐代码如下

伪代码(不是真正的php)

如果大写($order)'DESC',那么$order='ASC';
$query='选择…'+$秩序;
显式测试将任何注入代码转换回“ASC”,这样就可以安全地进行黑客攻击

当然,对于字段,您还可以对所有可能的字段名进行显式测试。只要你确保可能的结果只能是有效的字段名,你就很好,但这是如履薄冰

警告

现在,您(可能)又回到了处理查询字符串的行列中,您也回到了SQL注入领域,所以在操作时要格外小心。

漂亮的PDO代码,execute()不是只针对没有结果集的SQL语句吗?(更新/插入/删除)@Johan
PDOStatement::execute()
适用于任何语句-@Phil,好的,谢谢您学习了一个新的标题。绑定参数只能是值,不能是表达式(=在本例中为列名)。可能重复使用参数作为伪关键字将完全不起作用!这就是为什么使用参数可以防止SQL注入攻击的部分原因。你是说我在语句中没有正确使用参数吗?PHP的文档在WHERE子句中使用了它们,因此我认为我的应该可以很好地工作(但它没有):+1正是我想说的:)顺便说一句,我认为您可以省略directive关键字,它将假定为
ASC
。感谢您对此进行详细说明。我看到了您使用sprintf()所做的工作,明天将在工作中尝试类似的方法。我认为仅使用PDO的预处理语句就可以解决大多数SQL注入问题。我错了吗?我还需要清理参数吗?不,但您只能参数化值,因此如果您想通过粘贴字段名或顺序方向(ASC/DESC)来操作查询你又回到了攻击SQL查询字符串的行列,从而又回到了SQL注入的领域。忘了说谢谢你的帮助和澄清我现在面临的SQL注入威胁。我希望明天早上我能解决这个问题:)@Aaron,不客气。祝你好运,继续努力。
if uppercase($order) <> 'DESC' then $order = 'ASC';
$query = 'select ... '+ $order;