Почему PDO лучше подходит для экранирования запросов/строк MySQL, чем mysql_real_escape_string?

StackOverflow https://stackoverflow.com/questions/1742066

Вопрос

Мне сказали, что мне лучше использовать PDO для экранирования MySQL, а не mysql_real_escape_string.

Может быть, у меня сегодня безумный день (или это может быть тот факт, что я ни в малейшей степени не являюсь прирожденным программистом, и я все еще нахожусь на стадии новичка, когда дело касается PHP), но имея проверил руководство по PHP и прочитал запись на PDO, мне до сих пор неясно, что такое PDO и почему он лучше, чем использование mysql_real_escape_string.Возможно, это связано с тем, что я еще не совсем разобрался со сложностями ООП (я предполагаю, что это как-то связано с ООП), но, если не считать того факта, что переменные и значения массива, похоже, имеют двоеточие перед ними, Я до сих пор не уверен, что это такое на самом деле и как его использовать (и почему это лучше, чем mysql_real_escape_string.(Это также может быть как-то связано с тем фактом, что у меня нет четкого понимания того, что такое «классы», поэтому, когда я читаю «класс PDO», я на самом деле не стал мудрее).

Прочитав статья или два в разделе «Зона разработчика» на веб-сайте MySQL, я все еще не прояснил ситуацию.Поскольку на данный момент я даже не могу понять, что это такое, я думаю, что, возможно, использование этого сейчас немного выше моего понимания, но я все еще заинтересован в расширении своего образования и выяснении того, как я могу улучшить ситуацию.

Может ли кто-нибудь объяснить мне на «простом английском», что такое PDO (или указать мне направление к чему-то по этой теме, написанному на простом английском языке), и как вы будете его использовать?

Это было полезно?

Решение

Поскольку текущие ответы содержат подробную информацию, а ваш вопрос больше нацелен на общий обзор, я попробую:

Классы PDO призваны инкапсулировать всю функциональность, необходимую для взаимодействия с базой данных.Они делают это, определяя «методы» (OO-салон для функций) и «свойства» (OO-салон для переменных).Вы бы использовали их как полная замена для всех «стандартных» функций, которые вы сейчас используете для общения с базой данных.

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

Например, без PDO вы бы сделали что-то вроде этого:

// Get a db connection
$connection = mysql_connect('someHost/someDB', 'userName', 'password');
// Prepare a query
$query = "SELECT * FROM someTable WHERE something = " . mysql_real_escape_string($comparison) . "'";
// Issue a query
$db_result = mysql_query($query);
// Fetch the results
$results = array();
while ($row = mysql_fetch_array($db_result)) {
  $results[] = $row;
}

хотя это будет эквивалентно использованию PDO:

// Instantiate new PDO object (will create connection on the fly)
$db = new PDO('mysql:dbname=someDB;host=someHost');
// Prepare a query (will escape on the fly)
$statement = $db->prepare('SELECT * FROM someTable WHERE something = :comparison');
// $statement is now a PDOStatement object, with its own methods to use it, e.g.
// execute the query, passing in the parameters to replace
$statement->execute(array(':comparison' => $comparison));
// fetch results as array
$results = $statement->fetchAll();

Итак, на первый взгляд особой разницы нет, кроме синтаксиса.Но версия PDO имеет некоторые преимущества, самым большим из которых является независимость от базы данных:

Если вместо этого вам нужно обратиться к базе данных PostgreSQL, вам нужно всего лишь изменить mysql:к pgsql: в вызове экземпляра new PDO().При использовании старого метода вам пришлось бы просмотреть весь код, заменив все функции mysql_doSomething() их аналогом pg_doSomthing() (всегда проверяя потенциальные различия в обработке параметров).То же самое будет и со многими другими поддерживаемыми ядрами баз данных.

Итак, возвращаясь к вашему вопросу, PDO, по сути, просто дает вам другой способ достижения тех же целей, предлагая при этом некоторые ярлыки/улучшения/преимущества.Например, экранирование будет происходить автоматически, как это необходимо для используемого вами ядра базы данных.Кроме того, замена параметров (предотвращает SQL-инъекции, не показанные в примере) намного проще, что делает ее менее подверженной ошибкам.

Вам следует прочитать некоторые основы ООП чтобы получить представление о других преимуществах.

Другие советы

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

Запрос состоит из нескольких частей

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

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

'SELECT * FROM transactions WHERE username=$username'

Когда он получает эту строку, он должен проанализировать ее и решить: «Это SELECT с WHERE".

Перепутать детали

Предположим, злонамеренный пользователь вводит свое имя пользователя как billysmith OR 1=1.Если вы не будете осторожны, вы можете поместить это в свою строку, что приведет к:

'SELECT * FROM transactions WHERE username=billysmith OR 1=1'

...который вернется все транзакции для всех пользователей, потому что 1 всегда равно 1.Упс, вас взломали!

Посмотрите, что произошло? База данных не знала, какие части ожидать в вашем запросе., поэтому он просто проанализировал строку.Неудивительно, что WHERE было OR, с двумя условиями, которые могли бы его удовлетворить.

Держите детали прямо

Если бы оно только знало Что ожидать, а именно, SELECT чей WHERE имело только одно условие: злонамеренный пользователь не мог его обмануть.

Имея подготовленное утверждение, вы можете дать ему правильное ожидание.Вы можете сказать базе данных: «Я собираюсь отправить вам SELECT, и он будет ограничен строками WHERE username = веревка, которую я собираюсь вам дать.Вот и все — других частей в запросе нет.Вы готовы?Хорошо, вот строка для сравнения с именем пользователя».

С таким ожиданием базу данных не удастся обмануть:он будет возвращать только строки, в которых username столбец содержит фактическую строку 'Billysmith или 1 = 1.' Если ни у кого нет этого имени пользователя, оно ничего не вернет.

Другие преимущества подготовленных отчетов

Помимо преимуществ безопасности, подготовленные операторы имеют несколько преимуществ в скорости:

  • Их можно повторно использовать с разными параметрами, что должно быть быстрее, чем создание нового запроса с нуля, поскольку база данных уже знает, что вы собираетесь запросить.Он уже построил свой «план запроса».
  • Некоторые базы данных (я думаю, что Postgres является одной из них) начнут составлять план запроса, как только получат подготовленный оператор - до того, как вы фактически отправите параметры для использования с ним.Таким образом, вы можете увидеть ускорение даже при первом запросе.

Другое объяснение см. в ответе Тео. здесь.

В отличие от mysql_real_escape_string, PDO позволяет вам указать тип данных.

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

Обратите внимание, что в приведенном выше примере первый параметр «калории» должен быть целым числом (PDO::PARAM_INT).

Во-вторых, на мой взгляд, параметризованные запросы PDO легче читать.Я лучше прочитаю:

SELECT name FROM user WHERE id = ? AND admin = ? 

чем

SELECT name FROM user WHERE id = mysql_real_escape_string($id) AND admin = mysql_real_escape_string($admin);

В-третьих, вам не обязательно правильно указывать параметры.PDO позаботится об этом.Например, mysql_real_query_string:

SELECT * FROM user WHERE name = 'mysql_real_escape_string($name)' //note quotes around param

против

SELECT * FROM user WHERE name = ?

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

Представьте, что вы пишете что-то вроде:

$query = 'SELECT * FROM table WHERE id = ' . mysql_real_escape_string($id);

это не спасет вас от инъекций, потому что $id может быть 1 OR 1=1 и вы получите все записи из таблицы.вам придется привести $id к правильному типу данных (в данном случае int)

У pdo есть еще одно преимущество — взаимозаменяемость серверных частей базы данных.

Помимо предотвращения SQL-инъекций, PDO позволяет один раз подготовить запрос и выполнить его несколько раз.Если ваш запрос выполняется несколько раз (например, внутри цикла), этот метод должен быть более эффективным (я говорю «должен быть», потому что похоже, что это не всегда так в старых версиях MySQL).Метод подготовки/связывания также больше соответствует другим языкам, с которыми я работал.

Почему PDO лучше подходит для экранирования запросов/строк MySQL, чем mysql_real_escape_string?

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

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

Защиту можно примерно обеспечить в случае Я сбежал и процитировал свои данные, но он не везде применим, для идентификаторов например (как и PDO, кстати).

Итак, ответ:

  • PDO при экранировании привязанных значений применяет не только экранирование, но и кавычки — поэтому это лучше.
  • «побег» не является синонимом «защиты».«Экранирование + цитирование» примерно так.
  • но для некоторых частей запроса оба метода неприменимы.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top