2011-12-08 37 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您發佈的更新代碼是驗證您的輸入的一個很好的乾淨方式 - 它獲得我的投票。 –