Подтвердить что ты не робот

Когда * не * использовать подготовленные заявления?

Я перепроектирую веб-сайт, основанный на PHP, который использует минимальную базу данных. В исходной версии использовались "псевдоподготовленные-заявления" (функции PHP, которые выполняли кавычки и замену параметров), чтобы предотвратить атаки с помощью инъекций и отделить логику базы данных от логики страницы.

Кажется естественным заменить эти специальные функции объектом, который использует PDO и реальные подготовленные заявления, но после того, как я прочитал их, я не уверен. PDO по-прежнему кажется отличной идеей, но одна из основных точек продажи подготовленных заявлений заключается в том, что они могут повторно использовать их... которых я никогда не сделаю. Здесь моя настройка:

  • Все тривиально простые утверждения. Большинство из них находятся в форме SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1. Наиболее сложным выражением в партии является просто три таких выбора, соединенных вместе с UNION ALL s.
  • Каждый снимок страницы выполняет не более одного оператора и выполняет его только один раз.
  • Я нахожусь в размещенной среде и, следовательно, нахожусь в том, чтобы захлопывать их серверы, делая "стресс-тесты" лично.

Учитывая, что использование подготовленных инструкций будет, как минимум, удвоить количество обращений к базам данных, которые я делаю, мне лучше избегать их? Могу ли я использовать PDO::MYSQL_ATTR_DIRECT_QUERY, чтобы избежать накладных расходов на несколько поездок по базам данных, сохраняя при этом преимущества параметризации и защиты от инъекций? Или бинарные вызовы, используемые подготовленным оператором API, выполняются достаточно хорошо по сравнению с выполнением незаготовленных запросов, о которых я не должен беспокоиться об этом?

EDIT:

Спасибо за все хорошие советы, ребята. Это то, где я хотел бы отметить более одного ответа как "принятого" - много разных точек зрения. В конечном счете, я должен дать Рик его должное... без его ответа я бы блаженно ушел и сделал совершенно неправильную вещь даже после того, как после всех советов.: -)

Эмулированные подготовленные заявления!

4b9b3361

Ответ 1

Я думаю, вы хотите PDO:: ATTR_EMULATE_PREPARES. Это отключает собственные подготовленные операторы базы данных, но все же позволяет связывать запросы, чтобы предотвратить SQL-инъекцию и поддерживать ваш SQL-код. Из того, что я понимаю, PDO:: MYSQL_ATTR_DIRECT_QUERY полностью отключает привязки запросов.

Ответ 2

Сегодня правило разработки программного обеспечения: если оно ничего не сделает для вас, не используйте его.

Ответ 3

Когда не использовать подготовленные заявления? Когда вы собираетесь запускать инструкцию только до того, как соединение db исчезнет.

Если не использовать параметры связанных запросов (на самом деле большинство людей используют готовые заявления для получения)? Я склонен говорить "никогда", и я действительно хотел бы сказать "никогда", но реальность такова, что большинство баз данных и некоторые уровни абстракции db имеют определенные обстоятельства, при которых они не позволят вам связывать параметры, поэтому вы "вынуждены не использовать их в этих случаях. В любое другое время, тем не менее, это упростит вашу жизнь и ваш код станет более безопасным для их использования.

Я не знаком с PDO, но я бы сказал, что он предоставляет механизм для запуска параметризованных запросов со значениями, указанными в том же вызове функции, если вы не хотите готовиться, а затем выполняетесь как отдельный шаг. (например, что-то вроде run_query("SELECT * FROM users WHERE id = ?", 1) или тому подобное.)

Кроме того, если вы посмотрите под капотом, большинство слоев абстракции db подготовят запрос, а затем запустите его, даже если вы просто скажете ему выполнить статический оператор SQL. Таким образом, вы, вероятно, не спасаете поездку в db, избегая явных подготавливаний в любом случае.

Ответ 4

Подготовленные заявления используются тысячами людей и поэтому хорошо протестированы (и, следовательно, можно сделать вывод, что они достаточно безопасны). Ваше пользовательское решение используется только вами.

Вероятность того, что ваше настраиваемое решение небезопасна, довольно высока. Используйте подготовленные заявления. Вы должны поддерживать меньше кода таким образом.

Ответ 5

Преимущества подготовленных операторов следующие:

  • каждый запрос компилируется только один раз
  • mysql будет использовать более эффективный транспортный формат для отправки данных на сервер

Однако подготовленные заявления сохраняются только для каждого соединения. Если вы не используете пул соединений, не будет никакой пользы, если вы делаете только один оператор на странице. Тривиально простые запросы не выиграют от более эффективного транспортного формата.

Лично я бы не стал беспокоиться. Псевдоподготовленные утверждения, вероятно, будут полезны для безопасной переменной, которую они предположительно предоставляют.

Ответ 6

Честно говоря, я не думаю, что вам следует беспокоиться об этом. Тем не менее, я помню, что ряд фреймворков доступа к данным в формате PHP поддерживал режимы подготовки операторов и режимы без подготовки. Если я правильно помню, PEAR: DB сделал день назад.

Я столкнулся с той же проблемой, что и у вас, и у меня были свои собственные оговорки, поэтому вместо использования PDO я закончил писать свой собственный легкий уровень базы данных, который поддерживал подготовку и стандартное утверждение и выполнял правильное экранирование (sql-injection Prevention ) в обоих случаях. Одна из моих других попыток с подготовкой заключается в том, что иногда более эффективно добавлять некоторый неэскапируемый ввод в оператор, такой как... WHERE id IN (1, 2, 3...).

Я не знаю достаточно о PDO, чтобы рассказать вам, какие другие варианты вы используете. Тем не менее, я знаю, что у PHP есть функции, доступные для всех поддерживаемых ею поставщиков баз данных, и вы можете перевернуть свой собственный маленький слой поверх любого уровня доступа к данным, за которым вы застряли.