Pull to refresh
56
2.2
FanatPHP @FanatPHP

User

Send message
проблема в контексте.
сама по себе строка нормальная, в ней ничего ужасного нет.

но если она преподносится в контексте защиты от инъекций, то это, конечно, ужас.

плюс, если если функция посреди кода, а не внутри библиотечного метода — это тоже караул.

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

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

пагубность mysql_ заключается в двух вещах.
Первая чисто теоретическая — РНР-тим забил на эту либу и не хочет ее поддерживать. проблем с этим никаких нет, но теоретически ее могут в какой-то момент объявить deprecated.
Вторая заключается в том, что в коде не должно быть вызовов голого API. А должны быть — как совершенно правильно сделано у вас — вызовы функции- надстройки.

Единственно что, вместо ручной обработки передаваемых данных, лучше использовать автоматическую, с помощью плейсхолдеров:

$mdb->query( «SELECT * FROM table WHERE id =? AND name=?", $id, $name);

Это одновременно и упростит, и обезопасит код

а про быстроту там ниже ерунду написали
Ну, скажем, выбор технологий — mysql и PHP/PDO — достаточно красноречив.
Но если так уж хочется отстоять возможность написать на них демона, то да — для этих нескольких случаев статья будет смысл :)
Во-первых, склеивание не есть что-то ужасное, как вам, по всей видимости, кажется.
Любое веб-приложении по сути всегда работает с текстом, динамически формируя («склеивая») его из имеющихся фрагментов. Почему вы считаете это нормальным для случаев XML или HTML, но называете «велосипедом» для случая SQL — для меня загадка.

Во-вторых, с удовольствием ознакомился бы с примером такого варианта.
Во-первых, я видел цифры. Ради этих цифр статья и писалась. И если эти цифры заведомо на порядки ниже, чем в реальной жизни, то статья — фуфло.

Во-вторых, как я уже писал, в конкретном случае prepared statements это вообще не работает, поскольку prepare работает в пределах одного запуска скрипта. И для 5000 запусков картина будет совсем другая, нежели для 5000 циклов в пределах одного скрипта. Go figure.
Что бы он ни путал, но статья его — о первых.
Иначе ему придется признать использование mysql_real_escape_string() в php, которую он сам же и предал анафеме :)

Насчет профайлера — да, на стороне сервера это можно сделать. Именно в моей формулировке, «парсинг SQL и подстановка данных на место плейсхолдеров».
SQL Server Profiler никак не поможет мне в моей разработке, когда я составляю динамический запрос средствами серверного ЯП, и передаю для него данные средствами серверного ЯП.

Всё верно. Понятие «клиента» ввели в дискуссию вы сами.
Автор же статьи рассказывает нам о механизме работы родных подготовленных выражений, при которых подстановка данных производится на сервере. при использовании данной технологии обращений к серверу будет два. Вне зависимости от клиента. Это требование технологии.
Если вы не хотите ей пользоваться — предъявляйте претензии автору статьи, а не мне.
Это значит, что p5-DBI не использует встроенный механизм prepared statements, о котором говорит автор статьи, а лишь эмулирует его.
… то таких проверок пишется больше одной.
Дело в том, что «динамическое склеивание запросов» — не «велосипед», а насущная необходимость. В частности, для случаев «сложных форм поиска», о которых говорил автор оригинального комментария.

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

Да, и если в запрос подставляются данные, то это уже не статический запрос. Давайте будем точны в формулировках.
Не понял. С какой это стати нет гарантии? А в чем препятствия-то? Для запроса «с явными значениями» парсер не сможет отделить значение от ключевых слов, что ли? :)
Можно пример «профайлера», который берет на себя функции парсинга SQL и подстановки данных на место плейсхолдера?

Что такое идентификатор — в принципе, неважно (хотя и вполне понятно из приведенного рядом примера). Нам важен сам факт того, что подготовленные выражения для идентификаторов в принципе невозможны.

По поводу клиента, который требует отдельного обращения к БД — это не ко мне, а к автору топика. Это он ратует за их использование.
С точки зрения кэша запросов — разные.
С точки зрения кэша плана запросов — одинаковые.

Не будем менять топик на ходу, хорошо?
Статья — полная ерунда.
Любой тест производительности веб-приложения, который использует не siege, а «мильён пустых циклов» можно смело выкидывать в помойку. Поскольку в реальной жизни получится не 10%, а 0,1%.

причем в контексте подготовленных выражений это особенно актуально
В среднем веб-приложении не бывает 100500 запросов на один вызов.
А для 100500 вызовов будет выполнено 100500 prepare и 100500 execute, и статистика будет уже СОВСЕМ другая.
Ну так он прекрасно кэширует план и для обычных, неподготовленных запросов :)
О безопасности статических запросов заботиться не нужно — на то они и статические :)
Другое дело, если динамически в запрос подставляются не только данные.
Но вот если технология защиты требует разработчика «самого заботиться о безопасности», то грош ей цена.

А собирать условия в запросе на самом деле не так уж и сложно:

if ($_GET['num']) {
$sql .= «num = ?»;
$params[] = $_GET['num'];
}
Я с удовольствием поясню.
Prepared statement — это SQL запрос, который был предварительно prepared. То есть, это запрос, над которым совершили совершенно конкретную операцию — prepare() — отправив его на сервер БД с плейсхолдерами вместо данных.

Понятие плейсходера же гораздо шире. Это подстановка в общем смысле. %s в printf — это тоже плейсхолдер. И совсем не обязательно плейсхолдер в SQL должен быть реализован с помощью подготовленных выражений. Его можно обработать и на клиенте, руками. Причём клиентский плейсхолдер получается гораздо более гибким и полезным. В итоге запросы вполне могут быть безопасными и без использования подготовленных выражений. Причем даже более безопасными.
Напишу, пожалуй, о недостатках подготовленных выражений.

Как это часто бывает, страстными сторонниками того или иного явления или технологии являются неофиты. И это объяснимо — люди, которые давно работают, уже не испытывают того пиетета и желания срочно поделиться с окружающими.

В этом нет большой проблемы кроме той, что знания у неофита по большей части теоретические, из рекламных проспектов. В реальной же жизни не всё так красочно.

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

— при попытке вывести результирующий SQL мы видим все тот же запрос с плейсхолдерами, и выполнить его для отладки в консоли без плясок с бубном несколько затруднительно.

— такие конструкции, как IN(...). WHERE IN(:stroka_s_sapyatymi) почему-то не работает. Слабые духом сдаются и подставляют вместо плейсхолдера переменную. Сильные духом пишут специальный код для динамического составления оператора IN… И вместо сокращения кода мы получили его разрастание в несколько раз… Совсем не так все красиво оказалось, как в рекламе?

— идентификаторы. Опять разочарование. `:field_name` почему-то не работает. причем никакой код тут уже не помогает, увы.

Ну и по производительности. В силу технологических особенностей большинства веб-приложений (скрипт запускается для обслуживания реквеста и умирает) все преимущества сводятся на нет, а вот очевидная задержка — из-за того что для выполнения каждого запроса скрипт обращается к БД по два раза — объективно присутствует.
Автор не совсем понимает тему, на которую взялся писать.

«Достоинства»
(1) и (2) В типичном веб-приложении данные достоинства могут проявиться очень редко. Один и тот же запрос выполненный несколько раз в пределах одного и того же соединения — это, чаще всего, показатель кривого кода.
(3) Многие апологеты подготовленных выражений забывают, что кроме данных в запросах могут быть и другие динамические элементы.

«Ответы на комментарии»:
— Проблем у функциии mysql_real_escape_string практически нет. Проблема есть с пониманием, для чего она служит. Многие люди, действительно, полагают, что эта функция имеет какое-то отношение к инъекциям. Такая проблему существует, да. Но рекомендовать не использовать mysql_real_escape_string — это все равно что не рекомендовать пользоваться вилкой только потому, что некие люди зачем-то пытаются есть ей суп.

— PDO (и MySQLi) не панацея, о чем я писал выше.

Автор путает понятия «подготовленного выражения» и «плейсхолдера».

Ничего нет о недостатках подготовленных выражений.

А заблуждений, связанных с инъекциями, в народе действительно много.
Я подробно разбирал их на ПХПКонфе для желающих.
Блин, во тупняк-то. Так и знал, что где-нибудь накосячу =)
Когда я с самого начала тестировал по сети, выдавал только размер строки, а не её саму. И получил разницу в несколько rps. Что меня удивило и сподвигло на остальные тесты.

А сейчас провел siege нормально, с возвратом всей строки, плюс не в локалке, а через инет.
И получил ожидаемые 0,38 rps, на фоне которых наши 7 миллисекунд потерялись абсолютно.
Что и требовалось доказать: вынос проверки точек за цикл в условиях веб-приложения — экономия на спичках :-P

Information

Rating
1,190-th
Registered
Activity

Specialization

Backend Developer, Web Developer
Middle
From 140,000 ₽
PHP
OOP
MySQL
Linux
Git
SQL
Database
Nginx
Bash
Laravel