2009-06-10 9 views
13

Attualmente utilizzo Zend_Db per gestire le mie query. codice che ho scritto già che preforme query come quella qui sotto:evitare le iniezioni MySQL con la classe Zend_Db

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

Ho fatto questo senza igienizzante l'ingresso, assumendo Zend_Db sarà. Zend fa questo?

Un'altra domanda: Zend_Db disinfetta le query insert('table', $data) e update?

Grazie.

risposta

24

ho scritto un sacco di codice per i parametri del database e citando in Zend Framework mentre ero il team lead per il progetto (fino alla versione 1.0).

Ho cercato di incoraggiare le migliori pratiche laddove possibile, ma ho dovuto trovare un equilibrio con facilità d'uso.

Si noti che è sempre possibile esaminare il valore di stringa di un oggetto Zend_Db_Select, per vedere come ha deciso di fare quoting.

print $select; // invokes __toString() method 

Inoltre è possibile utilizzare il Zend_Db_Profiler per ispezionare il codice SQL che viene eseguito sul vostro conto da Zend_Db.

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

Ecco alcune risposte alle vostre domande specifiche:

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

    I valori sono espressi in modo appropriato. Sebbene "?" assomigli a un segnaposto per parametro, in questo metodo l'argomento viene effettivamente quotato in modo appropriato e interpolato. Quindi non è un vero parametro di query. In realtà, le due istruzioni seguenti producono esattamente la stessa query come l'utilizzo di cui sopra:

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

    Tuttavia, se si passa un parametro che è un oggetto di tipo Zend_Db_Expr, allora non è citato. Sei responsabile per i rischi di SQL injection, perché è interpolata pari pari, per sostenere valori di espressione:

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

    Qualsiasi altra parte di quella espressione che deve essere quotate o delimitato è la vostra responsabilità. Ad esempio, se si interpola qualsiasi variabile PHP nell'espressione, la sicurezza è una vostra responsabilità. Se i nomi di colonna sono parole chiave SQL, è necessario delimitarli autonomamente con quoteIdentifier(). Esempio:

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

    nome della tabella e delle colonne nomi sono delimitati, a meno che non si spegne AUTO_QUOTE_IDENTIFIERS.

    I valori sono parametrizzati come parametri di query reali (non interpolati). A meno che il valore non sia un oggetto Zend_Db_Expr, nel qual caso è interpolato letteralmente, quindi è possibile inserire espressioni o NULL o qualsiasi altra cosa.

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

    nome della tabella e delle colonne nomi sono delimitati, a meno che non si spegne AUTO_QUOTE_IDENTIFIERS.

    I valori sono parametrizzati, a meno che non si tratti di oggetti Zend_Db_Expr, come nel metodo insert().

    L'argomento $where non è filtrato affatto, quindi sei responsabile per qualsiasi rischio di iniezione SQL in quello. È possibile utilizzare il metodo quoteInto() per rendere più conveniente la quotatura.

+0

Ottima risposta, Bill e un ottimo componente a tutto tondo :) –

+0

Se si utilizza la funzione 'insert()' su un'istanza di 'TableGateway', l'escape delle colonne con nomi riservati viene eseguito automaticamente per te come indicato nel secondo punto sopra. Se lo si esegue manualmente (ad es. (SQL Server) 'array ([from] => 1));' produce un errore del database che dice ''[from]'' è un nome di colonna non valido. Quella colonna potrebbe essere stata sfuggita due volte come '[[from]]' –

1

Il bit che dovrebbe farti sentire al sicuro è il? segna nelle clausole where. Questi sono parametri, che vengono tranquillamente sostituiti con il secondo argomento dal sistema di database.

+1

non è il punto. Sprintf utilizza? segna pure. – erenon

+0

Sì, intendevo in relazione al metodo Zend_Db chiamate –

1

Quando avete bisogno di qualche altra parte (come in join) o non si è certi se sarà sfuggito allora si può sempre utilizzare $this->getAdapter()->quoteInto('type = ?',1);

2

per impostazione predefinita quando si utilizza vincolante valore nelle query SQL come questo:

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

Zend_Db utilizza la citazione appropriata dei valori per impedire l'iniezione SQL. sebbene sia fortemente raccomandato (da libri, articoli, manuali ed esperienza personale) per disinfettare/filtrare l'input dell'utente. Zend_Filter può essere molto utile.

0

L'input di filtraggio è sempre buono, perché probabilmente andrà da qualche altra parte oltre al DB, e almeno si vogliono dati saggi nel database ad un certo livello.

  • Zend_Filter_Input sul modo in
  • Le dichiarazioni preparate (o quoteInto se non in un preparato)
  • Escape Filtri sulla via d'uscita (htmlentities, ecc).
0

Una cosa su questo, quando il valore è NULL, è possibile achive non valida interrogazione

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

Risultato: errore di SQL

+0

In SQL, non è possibile utilizzare l'operatore = per confrontare a NULL comunque. –

+0

il mio esempio non riguarda i valori NULL, provo a mostrare che in alcuni casi è necessario controllare/convertire il tipo di valori da passare nelle funzioni sql-query build, questo è nel contesto della discussione – duganets

Problemi correlati