2009-06-10 150 views
13

我目前使用Zend_Db來管理我的查詢。 是瓶坯查詢類似下面的我已經寫代碼:避免MySQL注入Zend_Db類

$handle->select()->from('user_id') 
        ->where('first_name=?', $id) 
        ->where('last_name=?', $lname) 

我做這個沒有消毒的輸入,假設Zend_Db的會。 Zend是否這樣做?

另一個問題: Zend_Db是否清理insert('table', $data)update查詢?

謝謝。

回答

24

我寫了很多代碼的數據庫參數和報價Zend Framework,而我是該項目的團隊負責人(高達1.0版)。

我儘可能鼓勵最佳實踐,但我必須在易用性上取得平衡。

請注意,您始終可以檢查Zend_Db_Select對象的字符串值,以瞭解它是如何決定引用的。你

print $select; // invokes __toString() method 

也可以使用Zend_Db_Profiler檢查由Zend_Db代表您運行SQL。

$db->getProfiler()->setEnabled(true); 
$db->update(...); 
print $db->getProfiler()->getLastQueryProfile()->getQuery(); 
print_r $db->getProfiler()->getLastQueryProfile()->getQueryParams(); 
$db->getProfiler()->setEnabled(false); 

這裏有一些回答您的具體問題:

  • Zend_Db_Select::where('last_name=?', $lname)

    值進行適當引用。雖然「?」看起來像一個參數佔位符,但在此方法中,實際參數實際上是經過適當引用並插值的。所以它不是一個真正的查詢參數。事實上,以下兩個語句產生相同的查詢作爲上述用途:

    $select->where($db->quoteInto('last_name=?', $lname)); 
    $select->where('last_name=' . $db->quote($lname)); 
    

    但是,如果傳遞的參數是Zend_Db_Expr類型的對象,那麼它沒有報價。您負責SQL注入風險,因爲它是逐字插入,支持表達式的值:

    $select->where('last_modified < ?', new Zend_Db_Expr('NOW()')) 
    

    的表達需要被引用或分隔的任何其他部分是你的責任。例如,如果你在表達式中插入任何PHP變量,安全是你的責任。如果您的列名是SQL關鍵字,則需要使用quoteIdentifier()自行對它們進行分隔。例如:

    $select->where($db->quoteIdentifier('order').'=?', $myVariable) 
    
  • Zend_Db_Adapter_Abstract::insert(array('colname' => 'value'))

    表名和列名是分隔的,除非您關閉AUTO_QUOTE_IDENTIFIERS

    將值參數化爲真正的查詢參數(不是插值的)。除非值是一個Zend_Db_Expr對象,在這種情況下,它是逐字插入的,所以您可以插入表達式或NULL或其他。

  • Zend_Db_Adapter_Abstract::update(array('colname' => 'value'), $where)

    表名和列名是分隔的,除非您關閉AUTO_QUOTE_IDENTIFIERS

    值被參數化,除非它們是Zend_Db_Expr對象,如insert()方法。

    $where參數根本沒有被過濾,所以您應該對這個參數中的任何SQL注入風險負責。您可以使用quoteInto()方法來幫助使報價更方便。

1

應該讓你感覺安全的位是?標記在where子句中。這些參數是由數據庫系統安全地替換爲第二個參數。

+1

這不是重點。 sprintf使用?也標記。 – erenon 2009-06-11 13:59:53

+0

是的,我的意思是關於Zend_Db方法調用 – 2009-06-11 15:05:24

1

當你需要它在其他地方(如在加入),或者你不確定是否會被轉義,那麼你可以隨時使用$this->getAdapter()->quoteInto('type = ?',1);

2

默認情況下,當您使用值綁定在你的SQL查詢,像這樣:

where('first_name=?', $id); 

Zend_Db使用適當的值引用來防止SQL注入。儘管強烈建議(通過書籍,文章,手冊和自我體驗)來清理/過濾用戶輸入。 Zend_Filter可以非常有幫助。

0

過濾輸入總是很好,因爲它可能會去除數據庫以外的其他地方,並且您至少希望在某個級別上的數據庫中具有理智的數據。

  • 在途中Zend_Filter_Input
  • 準備語句(或者如果不quoteInto在一備)的出路(ヶ輛等)
  • 脫出過濾器。這個
0

一兩件事,當值爲NULL,則可以achive

$value = NULL; 
$select->where('prop=?', $value); 

結果不是有效的查詢:SQL錯誤

+0

在SQL中,無論如何您都不能使用=運算符來比較NULL。 – 2009-06-21 15:06:07