2009-06-10 4 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 для проверки SQL, выполняемую от вашего имени Zend_Db.

$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(), чтобы сделать предложение более удобным.

+0

Отличный ответ, Билл и отличный компонент all round :) –

+0

Если вы используете функцию 'insert()' в экземпляре 'TableGateway', экранирование столбцов с зарезервированными именами будет автоматически выполнено для вас, как указано во втором марке выше. Если вы вручную удалите его (т. Е. (SQL Server) »array ([from] => 1));' он выдает ошибку базы данных, в которой '' [from] ''является недопустимым именем столбца. Этот столбец мог быть дважды экранирован как '[[from]]' –

1

Немного, что должно заставить вас чувствовать себя в безопасности? отмечает в предложениях where. Это параметры, которые безопасно заменяются вторым аргументом системой базы данных.

+1

Дело не в этом. sprintf использует? также отмечает. – erenon

+0

Да, я имел в виду по отношению к вызовам метода Zend_Db –

1

Когда вам это нужно где-то еще (как в присоединиться), или вы не знаете, если она будет экранировать, то вы всегда можете использовать $this->getAdapter()->quoteInto('type = ?',1);

2

по умолчанию при использовании значения связывания в запросах SQL, как это:

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

Zend_Db использует соответствующее цитирование значений для предотвращения SQL-инъекции. хотя настоятельно рекомендуется (по книгам, статьям, учебным пособиям и самому опыту) для дезинфекции/фильтрации ввода пользователя. Zend_Filter может быть очень полезным.

0

Фильтрующий вход всегда хорош, потому что, скорее всего, он будет куда-то иным, чем только БД, и вы по крайней мере хотите, чтобы в вашей базе данных имелись нормальные данные.

  • Zend_Filter_Input на пути в
  • Подготовленные заявления (или quoteInto если не в подготовленный)
  • эвакуации фильтры на выходе (htmlentities и т.д.).
0

Одна вещь об этом, когда значение NULL, вы можете achive не допустимый запрос

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

Результат: Ошибка SQL

+0

В SQL вы не можете использовать оператор = для сравнения с NULL в любом случае. –

+0

мой пример не о значениях NULL, я пытаюсь показать, что в некоторых случаях вам нужно проверить/преобразовать тип значений для передачи в строковых функциях sql-query, это в контексте обсуждения. – duganets