Что делает bind_param?

Я учусь об исключении SQL-инъекций, и я немного смущен.

При использовании bind_param я не понимаю цели. На странице руководства я нашел этот пример:

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;

Теперь, если предположить, что эти 4 переменные были введены пользователем, я не понимаю, как это предотвращает инъекции SQL. По моему мнению, они все еще могут вводить все, что захотят.

Я также не могу найти объяснение для 'sssd' там. Что оно делает? Это то, что делает его безопасным?

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

Примечание. Этот вопрос объясняет, что делает bind_param, но я до сих пор не понимаю, почему он более безопасен или более защищен. Объяснение Bind_param

Ответ 1

Теперь, если предположить, что эти 4 переменных были введены пользователем, я не понимаю как это предотвращает инъекции SQL. По моему мнению, они все еще могут введите туда, где они хотят.

Основным принципом является использование подготовленного оператора, который предназначен для отправки безопасного запроса на сервер db, это может быть сделано путем исключения пользовательского ввода, который не является частью реального запроса, а также проверки запроса без какого-либо предложения where (where) для проверки правильности запроса перед использованием любых параметров.

Из этого вопроса: PDO отправляет необработанный запрос в MySQL, в то время как Mysqli отправляет подготовленный запрос, оба дают тот же результат

$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) {
$stmt->bind_param("i", $user);
$user = "''1''";

журналы сервера:

  130802 23:39:39   175 Connect   ****@localhost on testdb
    175 Prepare   SELECT * FROM users WHERE username =?
    175 Execute   SELECT * FROM users WHERE username =0
    175 Quit

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

Из руководства PHP http://php.net/manual/en/mysqli.quickstart.prepared-statements.php:

Экранирование и SQL-инъекция

Связанные переменные будут автоматически экранированы сервером. сервер вставляет свои экранированные значения в соответствующие места в перед выполнением. Подсказка должна быть предоставлена сервера для типа связанной переменной, чтобы создать соответствующий преобразование. См. Функцию mysqli_stmt_bind_param() для получения дополнительной информации. информация.

..

Я также не могу найти объяснение для 'sssd'. Что это делать? Это то, что делает его безопасным?

Ответ здесь: http://php.net/manual/en/mysqli-stmt.bind-param.php

i
corresponding variable has type integer

d
corresponding variable has type double

s
corresponding variable has type string

b
corresponding variable is a blob and will be sent in packets

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

Можете ли вы дать ссылку? Я думаю, вы неправильно поняли (mysql_real_escape_string())

Ответ 2

Используя подготовленные операторы, вы отделяете SQL-запросы от введенных пользователем данных. Вместо входных данных вы помещаете заполнители ('?' char) в свой SQL-запрос. Затем вы отправляете запрос на сервер СУБД (например, MySQL) с помощью метода "mysqli:: prepare". Поэтому сервер проверяет, что все в порядке, и если да, то ожидает входных данных. К настоящему времени он уже знает ваш запрос. Просто нужно ждать ввода данных для привязки к запросу.

В этот момент вступает в действие "bind_param", привязывание заполнителей к введенным пользователем данным. Обратите внимание, что bind_param привязывает данные только к заполнителям, оставляя неизменным запрос. Таким образом, не существует способа изменить исходный SQL-запрос, поскольку он уже отправлен на сервер с помощью метода подготовки и потому, что вы отправляете SQL-запросы и вводите данные отдельно, поэтому введенные пользователем данные не могут мешать запросам.

ИНАЧЕ...

Фактическая цель использования подготовленного оператора в SQL - это сократить затраты на обработку запросов, а не на разделение данных из запроса. Это то, как он используется сейчас, а не как он был разработан для использования в первую очередь.

'sssd' означает "string" , "string" , "string" и "double". На самом деле: $code - строка, $language - строка, $official - строка, а $percent - двойной тип.

mysqli_real_escape_string не устарел, но mysql_real_escape_string устарел (первый из них - mysqlI, где я обозначаю "улучшенный" ).