2012-09-15 28 views
1

我編寫了一個函數,用於從我的數據庫中選擇所有用戶,並使用PDO選擇所有相關字段。我還允許函數將一個數組作爲參數,以便於過濾。我的問題是,當我將過濾器數組傳遞給execute函數時,我沒有從我的表中獲取任何行。我知道它與PDO有關,以及我將數組傳遞給它的方式,因爲當我使用篩選器的execute方法運行execute方法時,它將硬編碼到查詢中。這裏是我的功能和代碼,它叫它:PDO執行不會正確注入數組值

$config = array(
    'filters' => array(
     'all members'  => array('', ''), 
     'officers'   => array('statuses.position_id', '8'), 
     'current members'  => array('users.alumni', 0) 
    ) 
); 

$filter = $config['filters']; 
//Requested filter is just a constant used to keep track of the parsed $_GET value 
$result = $dbh->getUsers($filter[REQUESTED_FILTER]); 

//Just showed function, not whole class 
public function getUsers(array $filter = array('', '')) { 
    $result = array(); 

    $sql = 'SELECT users.firstname, users.lastname, users.grad_year, users.alumni, users.signedISA, phone_numbers.phone_number, emails.email_address, 
       addresses.name, addresses.street, addresses.city, addresses.state, addresses.zip 
      FROM 
       ((users LEFT JOIN phone_numbers 
       ON users.user_id = phone_numbers.user_id) 
       LEFT JOIN emails 
       ON users.user_id = emails.user_id) 
       LEFT JOIN addresses 
       ON users.user_id = addresses.user_id 
       WHERE ? = ?;'; 

    $sth = $this->handle->prepare($sql); 

    if($sth->execute($filter)) { 
    while($row = $sth->fetch(PDO::FETCH_ASSOC)) { 
     array_push($result, $row); 
    } 
    } 

    return $result; 
} 

任何人都有任何想法,爲什麼這是行不通的?

回答

1

您不能將模式對象標識符(如表或列名稱)作爲參數傳遞給預準備語句(您當前的嘗試總是比較WHERE子句中的參數化字符串文字)。

相反,你需要做這樣的事情:

public function getUsers(array $filter = array('\'\'', '')) { 
    $result = array(); 

    $sql = 'SELECT users.firstname, users.lastname, users.grad_year, users.alumni, users.signedISA, phone_numbers.phone_number, emails.email_address, 
       addresses.name, addresses.street, addresses.city, addresses.state, addresses.zip 
      FROM 
       ((users LEFT JOIN phone_numbers 
       ON users.user_id = phone_numbers.user_id) 
       LEFT JOIN emails 
       ON users.user_id = emails.user_id) 
       LEFT JOIN addresses 
       ON users.user_id = addresses.user_id 
       WHERE ' . $filter[0] . ' = ?;'; 

    $sth = $this->handle->prepare($sql); 

    if($sth->execute($filter[1])) { 
    while($row = $sth->fetch(PDO::FETCH_ASSOC)) { 
     array_push($result, $row); 
    } 
    } 

    return $result; 
} 

當心SQL注入的如果$filter值是你的控制之外(你需要引用標識符與反引號和雙的任何包含在其中的反引號:確保你以多字節安全的方式做到這一點!)。

+0

我有一種感覺,它與此有關。 $ filter有些超出我的控制範圍,用戶可以更改查詢字符串來更改過濾器值。在運行此代碼之前,我一定會非常仔細地驗證來自查詢字符串的值。謝謝你的幫助,你爲我節省了很多時間。 – KylePlusPlus

+1

@KylePlusPlus我推薦**白名單**以確保標識符有效。如果過濾器可以是一個「僞查詢」,那麼首先解析它(無論需要什麼定義)並且*重建*它作爲SQL,**白名單**標識符和*綁定*值。這確保SQL注入是不可能的。 – 2012-09-15 02:02:47

+1

@KylePlusPlus此外,另一種減輕*安全漏洞的技術 - 在任何情況下都可以很好地實現,即使是在進行破壞/重建清理時也是如此 - 以「只讀」方式連接,以執行可能包含用戶定義的查詢,生成的輸入。 – 2012-09-15 02:08:37