Результат сохраняется в массиве $result
, а не в объекте PDO $one
. Это также нуждается в эхо, если вы не собираетесь использовать короткие ярлыки.
<input type="text" placeholder="<?php echo $result['gr_name']; ?>">
Я бы использовал ярлыки, так что если в настройках PHP они включены, но они устарели в PHP 5.6:
<input type="text" placeholder="<?= $result['gr_name']; ?>">
Пока вы можете использовать ярлыки, и я буду продолжать их использовать, чтобы протестовать против удаления этой невероятно полезной функции. Устаревшие ярлыки сломают множество тем WP и простых шаблонных движков!
Вам также следует рассмотреть возможность использования подготовленных заявлений . Без них этот скрипт уязвим для SQL-инъекций.
<?php
$query = $pdo->prepare("SELECT * FROM contactgroups WHERE id=:id");
if( $query->execute(array(':id' => $_GET['id'])) ) {
$result = $query->fetch();
?>
<input type="text" placeholder="<?php echo $result['gr_name']; ?>" />
<?php } ?>
Как PDO предотвращает SQL-инъекцию (слишком долго, чтобы добавить комментарий - прокрутите вниз, чтобы увидеть лучшее объяснение)
Начнем с запроса:
mysql_query("DELETE FROM users WHERE id='".$id."'");
Если $id = "' OR 1=1 --";
, то запрос будет выглядеть следующим образом при отправке в MySQL (- означает начало комментария):
DELETE FROM users WHERE id='' OR 1=1 --'
Очевидно, что последующее уничтожение может быть катастрофическим и, возможно, необратимым (если у вас нет умных администраторов БД). Исправление здесь, вместо использования длинного mysql_real_escape_string()
(я действительно никогда не понимал, почему имя функции было настолько многословным, во-первых), теперь мы можем использовать подготовленные операторы PDO.
По PDO::preparing()
заявлению, что вы отправляете сообщение в вашу БД с указанием сохранить и оптимизировать этот запрос, потому что он будет использоваться позже. Ваша БД хранит оптимизированный запрос, внимательно следя за тем, где находятся данные.
$statement = $pdo->prepare('DELETE FROM users WHERE id=:id');
PDO предоставит вам экземпляр PDOStatement , для которого вы можете PDO::bindParam()
значений и выполнить их. Итак, давайте сделаем это и выполним.
$statement->bindParam(':id', $id);
$statement->execute();
Теперь какая-то закулисная магия происходит здесь. PDO отправляет данные в MySQL. MySQL проверяет данные и вставляет их в подготовленный оператор. Зная, где данные должны были быть размещены и как долго были вставлены данные, MySQL может определить диапазоны символов в запросе, который не нужно выполнять (читай: данные).
Поэтому, когда хакер пытается выполнить SQL-инъекцию, MySQL даже не беспокоится об оценке чего-либо, связанного с подготовленным оператором.
- PDO сообщает MySQL,
"The data for :id is ' OR 1=1 --"
- MySQL находит место, где: id был в подготовленном операторе. (В данном примере символ 28)
- MySQL считает длину данных (в данном случае 11 символов)
- MySQL выполняет математику 1-го класса и помнит, что все символы от 28 до 39 должны рассматриваться как символы.
MySQL вставляет данные, и теперь запрос выглядит так:
DELETE FROM users WHERE id=' OR 1=1 --
Однако, поскольку он знает положение данных, MySQL только анализирует все, что находится за пределами каналов (|), для команд и ключевых слов.
DELETE FROM users WHERE id=|' OR 1=1 --|
Таким образом, текст между трубами фактически никогда не анализируется. Когда MySQL требуется сравнить идентификаторы, он все равно сравнивает идентификаторы в таблице с данными, но поскольку данные никогда не выполнялись, внедрение SQL завершается неудачей.
Лучшее объяснение того, как PDO предотвращает SQL-инъекции
Когда мы готовим оператор с помощью PDO, он уведомляет базу данных о предстоящем запросе и о том, где будут находиться данные в запросе. Когда мы связываем данные с этим запросом и выполняем его, база данных выполняет некоторые закулисные действия, чтобы убедиться, что SQL-инъекции сорваны.
Давайте возьмем это за кулисами работу в другом контексте. Вы управляете блогом PHP, чей движок вы написали полностью самостоятельно. Вы гордитесь умной системой комментариев, которую вы написали, пока какой-то придурок не решит опубликовать этот комментарий:
<script type="text/javascript">
alert('You just been H4X0RED!!!!1 LOLS');
</script>
После того, как вы выкриките четыре буквенные слова на экране компьютера и убедитесь, что сценарий, который родители малыша больше никогда не пускают в Интернет, вы устраняете уязвимость XSS в своем коде с помощью htmlspecialchars()
.
$comment_text = htmlspecialchars($_POST['comment_text']);
Теперь, что ты здесь сделал? Когда в 3 часа ночи просыпается сценарист и проскальзывает к своему компьютеру, чтобы снова попробовать код, htmlspecialchars()
превращает его неудачную попытку юмора в бесполезный беспорядок. Функция принимает любой важный в HTML символ (а именно <
и >
) и превращает их в буквальное значение (<
и >
).
<script type="text/javascript">
alert('You just been H4X0RED!!!!1 LOLS');
</script>
Анализатор HTML в браузере каждого пользователя интерпретирует <
не как начало тега HTML, а как признак фактического вывода символа <
. По сути, это то, что делает механизм базы данных со всеми данными, введенными в подготовленные операторы. За исключением случаев, когда буквы SQL составляют допустимые команды (а также действительные данные), механизм интерпретирует все символы в данных как их буквальное значение. Так что вместо:
DELETE FROM users WHERE id = 0 OR 1=1 --'
Он оценивает каждый символ в данных как его буквальное значение. В HTML это будет:
DELETE FROM users WHERE id = 0 OR 1=1 --'
Если вы посмотрите на оба здесь , они оба выводят одно и то же, за исключением второго, «данные» интерпретируются синтаксическим анализатором как его буквальное значение, а не как функциональное значение. SQL делает то же самое. Используя буквальное значение данных, ни один из фактических данных не может быть интерпретирован как команда или часть одного.