Когда * не * использовать подготовленные заявления? - PullRequest
34 голосов
/ 11 февраля 2009

Я реинжиниринг веб-сайта, управляемого 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:

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

эмулировал готовые утверждения это!

Ответы [ 6 ]

26 голосов
/ 11 февраля 2009

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

17 голосов
/ 11 февраля 2009

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

15 голосов
/ 11 февраля 2009

Когда не использовать готовые заявления? Когда вы только один раз запустите оператор, прежде чем соединение с БД прекратится.

Когда не для использования связанных параметров запроса (что на самом деле большинство людей используют для получения подготовленных операторов)? Я склонен сказать «никогда», и я действительно хотел бы сказать «никогда», но реальность такова, что большинство баз данных и некоторые уровни абстракции БД имеют определенные обстоятельства, при которых они не позволяют вам связывать параметры, поэтому вы Вы вынуждены не использовать их в этих случаях. Однако в любое другое время это сделает вашу жизнь проще, а ваш код - более безопасным для их использования.

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

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

8 голосов
/ 11 февраля 2009

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

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

7 голосов
/ 11 февраля 2009

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

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

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

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

2 голосов
/ 11 февраля 2009

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

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

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

...