错误! mysqli_escape_string()

时间:2013-12-29 22:07:18

标签: php mysql pdo

我对 php 相当新,并尝试在网上流传一些“教程”。我遇到的一个问题是关于“最新 php / MySQL 平台的旧教程。

例如:

public static function getList( $numRows=1000000, $order="publicationDate DESC" ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
        ORDER BY " . mysql_escape_string($order) . " LIMIT :numRows";

$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
$list = array();

while ( $row = $st->fetch() ) {
  $article = new Article( $row );
  $list[] = $article;
}

由于mysql_escape .. 已弃用,我正在尝试将其替换为mysqli_escape_string($conn, $order)。但我相信我的$st = $conn->prepare($sql)正在投掷猴子扳手。

有任何建议/解释吗?

2 个答案:

答案 0 :(得分:1)

您正在使用PDO,因此您应该使用准备好的查询。

也就是说,准备好的查询不适用于你想要做的事情。在任何情况下,mysql_real_escape_string都不会在此保存。

相反,您可以尝试一些自定义转义:

"... ORDER BY `".str_replace(array("`","\\"),"",$order)."` LIMIT ...";

反引号很有用! :P

答案 1 :(得分:1)

好几个问题:

  • 您无法将mysql_*功能与PDO混合使用。我知道它令人困惑,因为PHP有​​三个三个不同的MySQL用于MySQL。但你必须一次使用一个。

  • 转义函数(包括PDO::quote())仅用于转义字符串文字和日期文字。他们没有为列名做正确的事。

  • 您的$order变量有两个语法元素:列和方向。即使您要正确引用该列,您也不希望在引号中包含DESC

  • 方向(ASC / DESC)是一个SQL关键字,因此不会引用引号。因此,没有可能逃避SQL注入的安全性。

我的解决方案不是使用引用/转义,而是使用白名单。并使排序列与排序方向分开。

public static function getList( $numRows=1000000, $order="publicationDate", $direction="DESC" ) {

    $columns = array("publicationDate"=>"publicationDate", "name"=>"authorName", "DEFAULT"=>"publicationDate");
    $directions = array("up"=>"ASC", "down"=>"DESC", "DEFAULT"=>"DESC");

    $order_column    = $columns[$order] ?: $columns["DEFAULT"];
    $order_direction = $directions[$direction] ?: $directions["DEFAULT"];

    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate 
        FROM articles
        ORDER BY $order_column $order_direction LIMIT :numRows";
    . . .
 }

提示:我从不使用SQL_CALC_FOUND_ROWS,因为它是一个如此可怕的性能杀手。实际上,运行两个查询要好得多,一个获得SELECT COUNT(*)...,第二个获得有限的结果集。
请参阅To SQL_CALC_FOUND_ROWS or not to SQL_CALC_FOUND_ROWS?

上的测试