2011-12-08 36 views
0

这是我正在准备的查询。这看起来像一个普通的mysql_query,我不确定我是否超出了PDO的安全边界。是否在PDO注入中安全地使用绑定参数构建查询?

function opinionlist($orderby="dateposted desc",$page="0",$pagesize="10"){ 
    $dbh = new PDO(...); 
    $s = $dbh->prepare("select * from fe_opinion 
         order by :orderby limit :page,:pagesize"); 
    $s->bindParam(":orderby", $orderby); 
    $s->bindParam(":page", $page); 
    $s->bindParam(":pagesize, $pagesize"); 
    $s->execute(); 
    $opinionlist = $s->fetchAll(PDO::FETCH_ASSOC); 
    echo json_encode($opinionlist); 
} 
  1. 我可以放心地建立这样的查询?
  2. 正在通过声明安全地获取订单的表名,还是我应该 仅限从输入中获取值?

目前我改变了我的代码

function opinionlist($orderby="dateposted desc",$page="0",$pagesize="10"){ 
    $orderbylist=array("dateposted desc","countcomment desc","countvote desc"); 
    $dbh = new PDO(...); 
    if(!in_array($orderby, $orderbylist)){$orderby="dateposted desc";} 
    $s = $dbh->prepare("select * from fe_opinion order by $orderby limit :page,:pagesize"); 
    $s->bindParam(":page", $page); 
    $s->bindParam(":pagesize, $pagesize"); 
    $s->execute(); 
    $opinionlist = $s->fetchAll(PDO::FETCH_ASSOC); 
    echo json_encode($opinionlist); 
} 
+0

这可能实际上不适用于“LIMIT”。参数不会替换串联的变量。你可以做'LIMIT:offset,:limit',但是你不能用单个参数替换整个LIMIT子句。 –

+0

@Michael我改变了页面参数,我的查询仍然获取按语句顺序的表名。除了价值注入安全之外,还有其他的东西吗? –

+1

你不能“绑定”列名。这不是一个准备好的声明,而是使其再次变得动态。 – mario

回答

1

它来验证你输入的类型和内容很好的实践。

可以消毒$orderbymysql_real_escape_string()或拒绝$orderby不包含单一有效的列名后跟一个可选ascdesc的值(甚至一个逗号分隔的这些列表,如果你愿意的话)。您可以通过硬编码或请求该表的列表(来自INFORMATION_SCHEMA)来确定有效列的列表。

当然,您可以使用is_numeric()代替$page$pagesize

有了这个功能,您不仅可以覆盖SQL注入,还可以让您的代码更健壮。


小更新:当你发现,你不能用一个参数$orderby

+0

通过PDO使用预准备语句时,不需要转义值。 PDO自动处理。 –

+1

@MichaelMior pdo只能转义绑定参数。 –

+0

@UğurGümüşhan您发布的更新代码是验证您的输入的一个很好的干净方式 - 它获得我的投票。 –