Intereting Posts
Ошибка PHP, MySQL: количество столбцов не соответствует количеству значений в строке 1 Динамически создавать функции класса PHP Создание уникальной случайной строки определенной длины и ограничений в PHP? Предупреждение: mysqli_connect (): Неизвестный сервер сервера MySQL Можно ли несколько раз вызвать curl_setopt с CURLOPT_HTTPHEADER, чтобы установить несколько заголовков? Как этот PHP закодирован? Какой хэш используют сеансы PHP при хранении идентификатора? PHP Curl post с прикреплением файла; настраиваемый заголовок типа содержимого php url routing question Как предотвратить ошибку «недействительный файл изображения» при использовании функции GD imagecreatefrom * in php? Переменная от Javascript -> Php -> Smarty … возможно ли это? PHP или htaccess делают страницу динамического URL-адреса равным 404, когда элемент отсутствует в БД квадратная скобка json array PHP обнаруживает (или удаляет) текущую букву диска? Ошибка Paypal. Мы сожалеем. В настоящий момент, похоже, не работает.

Должны ли вы использовать подготовленные заявления только для их экранирования?

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

Каждое подготовленное заявление занимает серверные ресурсы. Заявления должны быть немедленно закрыты сразу после использования. Если это не сделано явно, оператор будет закрыт, когда дескриптор оператора будет освобожден PHP.

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

С http://php.net/manual/en/mysqli.quickstart.prepared-statements.php

Учитывая вышеизложенное, если вы только собираетесь использовать запрос один раз, не лучше ли использовать подготовленные заявления?

Разница считается незначительной.

Тем не менее, нужно отличить подготовленные заявления от общей идеи подготовленного заявления.

Первый – это просто форма запросов, поддерживаемых большинством СУБД, объясненных здесь . Его использование может быть поставлено под сомнение.
Последнее представляет собой общее представление о замене фактических данных заполнителем, что подразумевает дальнейшую обработку замещенных данных. Он широко используется в программировании, примером является известная функция printf() . И этот последний подход должен быть ВСЕГДА использоваться для запуска запроса к базе данных , независимо от того, поддерживаются ли он родными подготовленными операциями или нет. Потому как:

  • подготовленный оператор делает правильное форматирование (или обработку) неизбежным .
  • подготовленный оператор делает правильное форматирование (или обработку) только в правильном месте – прямо перед выполнением запроса, а не в другом месте, поэтому наша безопасность не будет полагаться на такие ненадежные источники, как
    • некоторая функция «волшебства» PHP, которая скорее портит данные, чем делает их безопасными.
    • доброжелательность одного (или нескольких) программистов, которые могут решить форматировать (или не форматировать) нашу переменную где-то в потоке программы. Это очень важно.
  • подготовленный оператор влияет на самое значение, которое входит в запрос, но не на исходную переменную, которая остается неповрежденной и может использоваться в следующем коде (который будет отправлен по электронной почте или показан на экране).
  • подготовленный оператор может сделать код приложения значительно короче, делая все форматирование за кулисами (* только если водитель разрешает).

Таким образом, даже если вы считаете, что не используете собственные подготовленные операторы (это вполне нормально), вы всегда должны создавать свои запросы, используя заполнители вместо фактических данных. Для этого вы можете использовать PDO , который работает точно так же, как описано выше – по умолчанию он просто подражает подготавливает , означает, что обычный SQL-запрос создается из подготовленного запроса и данных, а затем выполняется против базы данных.

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

Если вы не можете сравнить это и доказать, что у них есть измеримое сопротивление производительности, как в чем-то более чем на 10-15% медленнее, нет никаких оснований суетиться по этому поводу. Даже тогда, это небольшая цена, чтобы заплатить за почти полную уверенность в целостности данных, предполагая, что вы используете только заполнители.

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

Любой, кто считает себя профессиональным программистом, должен будет периодически проверять свое приложение, чтобы убедиться, что в нем нет ошибок SQL-инъекций. Если не очевидно, что что-то ускользнуло, нельзя полагать, что его избегают, поэтому вы должны исследовать.

Заполнители также уменьшают вероятность ошибочного смешивания столбцов и связанных с ними значений. Функция названных параметров PDO отлично справляется с этим.

Подготовка инструкции дает план запроса, подходящий для переменных. Затем он остается доступным для многократного использования.

Есть связанные с ними мутации, кстати. Рассмотрим это утверждение:

 select * from posts order by post_date limit 10 offset ?; 

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

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

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

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

Константы в порядке.

 $sql = "SELECT * FROM foobar"; 

Если нет никакой вероятности, что переменная $ id будет содержать любой другой тип данных, чем int, тогда это нормально.

 $sql = "SELECT * FROM users WHERE id=".$id; 

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