Intereting Posts
Ошибка при echo $ _GET Ошибка при создании соединения с PDO в PHP PHP – Передача переменных с одной страницы на другую Организация дат со временем и часовыми поясами. (Преобразование в точную метку времени.) MongoDB Aggregation PHP, группа по часам Нужен PHP-скрипт для распаковки и прокрутки зашифрованного файла Отправить форму – Предотвращение перезагрузки страницы jQuery Узнайте, есть ли функция с выходом php CodeIgniter: Try Catch не работает в классе модели CakePHP 2.5.7 – Ошибка аутентификации при входе в систему с нестандартным пользователем Как вызвать функцию одного php-файла из другого php-файла и передать ему параметры? Рекурсивное удаление Измените эту функцию js так, чтобы она использовала значение, полученное из db вместо значений, указанных в массиве, для генерации опций Select Woocommerce WC_Order get_shipping_address () не возвращается как массив Передать переменную js, чтобы сформировать URL-адрес действия

Как создать безопасный mysql подготовленный оператор в php?

Я новичок в использовании подготовленных операторов в mysql с php. Мне нужна помощь в создании подготовленного оператора для извлечения столбцов.

Мне нужно получить информацию из разных столбцов. В настоящее время для тестового файла я использую абсолютно незащищенную инструкцию SQL:

$qry = "SELECT * FROM mytable where userid='{$_GET['userid']}' AND category='{$_GET['category']}'ORDER BY id DESC" $result = mysql_query($qry) or die(mysql_error()); 

Может ли кто-нибудь помочь мне создать безопасный оператор mysql с использованием ввода параметров URL (как указано выше), который подготовлен?

БОНУС: Подготовленные заявления также предполагают увеличение скорости. Будет ли она увеличивать общую скорость, если я использую только подготовленное заявление три или четыре раза на странице?

Вот пример использования mysqli (object-syntax – довольно легко перевести на синтаксис функции, если вы желаете):

 $db = new mysqli("host","user","pw","database"); $stmt = $db->prepare("SELECT * FROM mytable where userid=? AND category=? ORDER BY id DESC"); $stmt->bind_param('ii', intval($_GET['userid']), intval($_GET['category'])); $stmt->execute(); $stmt->store_result(); $stmt->bind_result($column1, $column2, $column3); while($stmt->fetch()) { echo "col1=$column1, col2=$column2, col3=$column3 \n"; } $stmt->close(); в $db = new mysqli("host","user","pw","database"); $stmt = $db->prepare("SELECT * FROM mytable where userid=? AND category=? ORDER BY id DESC"); $stmt->bind_param('ii', intval($_GET['userid']), intval($_GET['category'])); $stmt->execute(); $stmt->store_result(); $stmt->bind_result($column1, $column2, $column3); while($stmt->fetch()) { echo "col1=$column1, col2=$column2, col3=$column3 \n"; } $stmt->close(); 

Кроме того, если вам нужен простой способ захвата ассоциативных массивов (для использования с SELECT *) вместо того, чтобы точно указать, к каким переменным привязать, вот удобная функция:

 function stmt_bind_assoc (&$stmt, &$out) { $data = mysqli_stmt_result_metadata($stmt); $fields = array(); $out = array(); $fields[0] = $stmt; $count = 1; while($field = mysqli_fetch_field($data)) { $fields[$count] = &$out[$field->name]; $count++; } call_user_func_array(mysqli_stmt_bind_result, $fields); } 

Чтобы использовать его, просто вызовите его вместо вызова bind_result:

 $stmt->store_result(); $resultrow = array(); stmt_bind_assoc($stmt, $resultrow); while($stmt->fetch()) { print_r($resultrow); } в $stmt->store_result(); $resultrow = array(); stmt_bind_assoc($stmt, $resultrow); while($stmt->fetch()) { print_r($resultrow); } 

Вы можете написать это вместо этого:

 $qry = "SELECT * FROM mytable where userid='"; $qry.= mysql_real_escape_string($_GET['userid'])."' AND category='"; $qry.= mysql_real_escape_string($_GET['category'])."' ORDER BY id DESC"; 

Но чтобы использовать подготовленные заявления, вам лучше использовать общую библиотеку, например PDO

 <?php /* Execute a prepared statement by passing an array of values */ $sth = $dbh->prepare('SELECT * FROM mytable where userid=? and category=? order by id DESC'); $sth->execute(array($_GET['userid'],$_GET['category'])); //Consider a while and $sth->fetch() to fetch rows one by one $allRows = $sth->fetchAll(); ?> 

Или, используя mysqli

 <?php $link = mysqli_connect("localhost", "my_user", "my_password", "world"); /* check connection */ if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $category = $_GET['category']; $userid = $_GET['userid']; /* create a prepared statement */ if ($stmt = mysqli_prepare($link, 'SELECT col1, col2 FROM mytable where userid=? and category=? order by id DESC')) { /* bind parameters for markers */ /* Assumes userid is integer and category is string */ mysqli_stmt_bind_param($stmt, "is", $userid, $category); /* execute query */ mysqli_stmt_execute($stmt); /* bind result variables */ mysqli_stmt_bind_result($stmt, $col1, $col2); /* fetch value */ mysqli_stmt_fetch($stmt); /* Alternative, use a while: while (mysqli_stmt_fetch($stmt)) { // use $col1 and $col2 } */ /* use $col1 and $col2 */ echo "COL1: $col1 COL2: $col2\n"; /* close statement */ mysqli_stmt_close($stmt); } /* close connection */ mysqli_close($link); ?> 

Я согласен с несколькими другими ответами:

  • В ext/mysql PHP нет поддержки параметризованных операторов SQL.
  • Параметры запроса считаются более надежными в защите от SQL-инъекций.
  • mysql_real_escape_string() также может быть эффективным, если вы используете его правильно, но он более подробный для кода.
  • В некоторых версиях международные наборы символов имеют случаи символов, которые не удаляются должным образом, оставляя тонкие уязвимости. Использование параметров запроса позволяет избежать этих случаев.

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

 $query = "SELECT * FROM $the_table ORDER BY $some_column"; 

Что касается производительности:

  • Преимущество производительности возникает, когда вы выполняете подготовленный запрос несколько раз с разными значениями параметров. Вы избегаете накладных расходов на разбор и подготовку запроса. Но как часто вам приходится выполнять один и тот же SQL-запрос много раз в одном и том же запросе PHP?
  • Даже когда вы можете воспользоваться преимуществами этой производительности, это, как правило, лишь небольшое улучшение по сравнению со многими другими вещами, которые вы могли бы сделать для решения проблемы производительности, например, с помощью кэширования операций с окнами или кэширования данных.
  • Есть даже некоторые случаи, когда подготовленный запрос вредит производительности. Например, в следующем случае оптимизатор не может предположить, что он может использовать индекс для поиска, поскольку он должен предположить, что значение параметра может начинаться с шаблона:

     SELECT * FROM mytable WHERE textfield LIKE ? 

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

На мой взгляд, два наиболее важных пункта:

  • SQL Injection: Обязательно mysql_real_escape_string() всех ваших переменных запроса с mysql_real_escape_string() функции mysql_real_escape_string() PHP (или чего-то подобного).
  • Проверка ввода: никогда не доверяйте вводам пользователя. См. Это для руководства по правильной дезинфекции и проверке ваших входов.

Подготовленные утверждения не поддерживаются простым старым интерфейсом Mysql / PHP. Вам понадобится PDO или mysqli . Но если вы просто хотите заменить заполнители, отметьте этот комментарий на странице руководства пользователя mysql_query php.

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

Это аккуратный маленький класс, который обертывает и скрывает большую часть трещины, которая накапливается при использовании raw mysqli, так что при использовании подготовленных операторов требуется только одна или две строки поверх старого интерфейса mysql / php