Если все запросы SQL должны быть подготовлены для предотвращения инъекций SQL, почему синтаксис допускает неподготовленные запросы? - PullRequest
2 голосов
/ 05 мая 2020

Поскольку все SQL запросы должны быть подготовлены для предотвращения SQL инъекций, почему нам разрешено писать и выполнять неподготовленные запросы? Разве это не кажется нелогичным?

Ответы [ 3 ]

2 голосов
/ 05 мая 2020

В случаях, когда запрос представляет собой фиксированную строку и не требует каких-либо программных переменных, можно безопасно использовать query() для его запуска.

Вот пример из https://www.php.net/manual/en/pdo.query.php :

<?php
$sql = 'SELECT name, color, calories FROM fruit ORDER BY name';
foreach ($conn->query($sql) as $row) {
    print $row['name'] . "\t";
    print $row['color'] . "\t";
    print $row['calories'] . "\n";
}

В запросе нет PHP переменных. query() достаточно, и он выполняет то же самое, что и prepare() и execute().

Если вам нужно заменить PHP переменные на значения в SQL выражениях, вы должны использовать параметры:

$sql = 'SELECT name, colour, calories FROM fruit
    WHERE calories < :calories AND colour = :colour';
$sth = $dbh->prepare($sql);
$sth->execute(array('calories' => 150, 'colour' => 'red'));

Вы можете обнаружить, что это чаще встречается в вашем приложении, чем выполнение фиксированного запроса.

1 голос
/ 05 мая 2020

Связанные параметры и подготовка запроса - это разные вещи. Вы можете сделать одно или другое или оба.

Вам необходимо связать параметры, чтобы предотвратить внедрение SQL. Однако есть вещи, которые нельзя передать в качестве параметров (например, список ORDER BY), и в этом случае вы можете объединить желаемый синтаксис SQL непосредственно в строку SQL. Это называется «Dynami c SQL» и обычно должно использовать только строки из белого списка, чтобы предотвратить внедрение SQL.

Итак, чтобы ответить (как я думаю) вы задаете вопрос: Dynami c SQL разрешено, потому что есть случаи, не охваченные связанными параметрами.

1 голос
/ 05 мая 2020

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

$sql = "SELECT * FROM someTable WHERE id = $id";
$stmt = $conn->prepare($sql);
...