LINUX.ORG.RU

PHP. Зачем подготавливать запросы при выборке данных?

 , , , ,


0

1

О-о-очень боялся задать вопрос связанный с PHP, ибо тьма ненавидящих его, но пусть меня закидают тухлой шаурмой с вокзала и какой-нибудь гуру даст ответ…=)

В общем есть интерес к этому ЯП (да стану я писать на PHP красиво и шагну я в мир CRUD’а хотя бы). К примеру есть у меня в МУСКУЛ’е БД с таблицей users и полями в ней id, name и surname с соответствующими данными. Где-то пишут, чтоб выполнить SELECT * FROM users, надо подготовить запрос. Зачем? Какая опасность может подстерегать при выборке?

★★

Если я правильно понемаю, о чём идёт речь, то речь идёт о том, что не надо конструировать параметризованные запросы ручной конкатенацией/интерполяцией строк, потому что это создаёт потенциальную дыру в безопасности. Нужно использовать какой-нибудь PreparedStatement.

Нет параметров у запроса — нет необходимости извращаться. Так своему лиду и объясни.

Только вежливо, а то знаю я вас.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

Не, не, не. Изврат в плане обучения пихе исключительно только моё желание. Я может не так объяснил. Для чего подготавливать запросы (prepare, execute) при добавления данных - это понятно. Чтоб быть уверенным что в запрос не пойдёт инъекция. А вот зачем при попытке вывести в браузер то, что уже есть в БД, я не совсем понимаю. Как это может навредить базе?

Shprot ★★
() автор топика
Ответ на: комментарий от Shprot

Если есть запрос SELECT * FROM users WHERE id = $id, то поставляем в $id = «1; DROP TABLE users» и больше такой таблицы нет.

https://xkcd.com/327/

NeOlip ★★
()
Последнее исправление: NeOlip (всего исправлений: 1)
Ответ на: комментарий от NeOlip

поставляем в $id = «1; DROP TABLE users» и больше такой таблицы нет.

Оу щет…! =) На тестовой БД сейчас попробовал и всё сработало! =)
Спасибо! Самое понятное объяснение…=)

Shprot ★★
() автор топика

О-о-очень боялся задать вопрос связанный с PHP, ибо тьма ненавидящих его

Вопрос, насколько я его понимаю, с PHP не связан. Понятие prepared queries есть практически у всех РСУБД, и ЯП клиента вообще не важен.

Помимо защиты от инъекций, о которой уже написали, есть ещё элемент оптимизации. Если у тебя есть в приложении используются запросы одинаковой формы, отличающиеся параметрами, то использование prepared query вместо «ручного» формирования строки SQL позволит базе быстро «осознать» этот факт и избежать лишней работы. К SELECT * FROM users это, разумеется, не относится — нужен более сложный запрос с параметрами.

annulen ★★★★★
()

На самом деле не только для этого. Ведь ничто не мешает эскейпить параметры через mysql_real_escape_string перед конкатенацией. Здесь идея в том что когда делается несколько одинаковых по сути запросов но с разными параметрами, то можно сэкономить на этапах парсинга запроса и вычисления оптимального плана выполнения запроса

cobold ★★★★★
()

Шел 2024, php-шники до сих пор не осилили ORM. Имхо, начинать нужно с ORM для понимания архитектуры и связей. А уж ручная оптимизация запросов и вот это вот всё требуется в вебе не так уж и часто и в хороших ORM делается с полпинка и без инъекций, возни со всем этим ручным экранированием и закатом солнца вручную

menangen ★★★★★
()
Ответ на: комментарий от Shprot

Меня вот одно смущает, что здесь ты вроде бы понимаешь что такое инъекции, а постом ниже уже удивляешься хрестоматийному примеру инъекции.

На самом деле prepare не обязателен чтобы защититься от инъекций, так как почти в каждой БД есть специальный синтаксис для безопасной подстановки параметров и без prepare, что-нибудь вроде id = ? или id = $1. Всё что делает prepare это создаёт скомпилированный запрос в кэше БД, который можно затем с любыми параметрами запустить без разбора текста запроса заново. И ещё почему-то дизайнеры пыхи решили в некоторых драйверах сделать шаг с prepare обязательным, вроде бы для унификации разных апи.

neumond
()
Ответ на: комментарий от menangen

Мне сама идея ORM кажется какой-то глупой. Ну не будут реляционные данные никогда работать как обычные объекты в памяти, чтобы я мог пройти по ним циклом и что-то посчитать или поменять. А вот хороший конструктор типовых запросов и удобное описание табличек классами это неплохо.

neumond
()
Ответ на: комментарий от cobold

Ведь ничто не мешает эскейпить параметры через mysql_real_escape_string перед конкатенацией.

Практика показывает, что с подготовленными выражениями кожаные мешки гораздо реже косячат.

NeOlip ★★
()

Подготовленные запросы имеют две цели:

1) сократить расходы проца на парсинг запроса каждый раз (он будет парситься только один раз при подготовке)

2) уменьшить шанс дыры если забудешь где-то что-то экранировать

Поскольку время выполнения запроса почти в 100% случаев несоизмеримо больше времени его парсинга, то первый пункт можно не учитывать. Второй важен если ты нуб и часто что-то забываешь. Если пишешь всё аккуратно то он тоже становится не совсем важен.

Однако есть ещё два аспекта, не совсем такие прямые:

1) идеологически правильнее таки готовить запрос заранее

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

firkax ★★★★★
()
Ответ на: комментарий от NeOlip

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

firkax ★★★★★
()
Ответ на: комментарий от Partisan

Использование ORM для избавления от необходимости изучать SQL неправильно.

Вне зависимости от контекста? Почему? Что скажешь на счёт использования ASM для избавления от необходимости изучения машкода? WASM для … JS? ElmUI для … HTML/CSS? WYSIWYG редактор для … LaTex? Rust для … C++?

CommonLispPrgrmmng
()