Я изучал bindValue()
PDO bindValue()
. Я знаю, что подготовка моих операторов SQL с PDO ведет к тому, что SQL-инъекции происходят.
Пример кода:
$stmt = $dbh->prepare('SELECT * FROM articles WHERE id = :id AND title = :title'); $stmt->bindValue(':id', PDO::PARAM_INT); $stmt->bindValue(':title', PDO::PARAM_STR); $stmt->execute();
Связывая идентификатор как число, а заголовок был строкой, мы можем ограничить ущерб, нанесенный, когда кто-то пытается выполнить SQL-инъекцию внутри кода.
Должны ли мы всегда связывать наши значения с PDO::PARAM_
поэтому мы можем ограничить то, что можно извлечь из базы данных в SQL-инъекции? Означает ли это повышение безопасности с помощью PDO при выполнении bindValue()
?
В одном есть два вопроса. Важно не путать их
Хотя для второго, ради здравого смысла кода и СУХОЙ –
Существует много способов избежать ручной привязки. Некоторые из них:
ORM – отличное решение для простых операций CRUD и должно иметь в современном приложении. Он полностью скроет SQL от вас, сделав привязку за кулисами:
$user = User::model()->findByPk($id);
Query Builder – это также путь, который скрывает SQL в некоторых PHP-операциях, но снова скрывает привязку за кулисами:
$user = $db->select('*')->from('users')->where('id = ?', $id)->fetch();
некоторые библиотеки абстракции могут позаботиться о переданных данных с помощью типа-намеченных заполнителей , снова спрятав фактическое привязку:
$user = $db->getRow("SELECT * FROM users WHERE id =?i", $id);
если вы все еще используете PHP в прошлом столетии и имеете необработанный PDO по всему коду – тогда вы можете передать свои переменные в execute (), сохраняя при этом много ввода:
$stmt = $dbh->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([$id]); $user = $stmt->fetch();
Начиная с третьего вопроса – пока вы связываете числа как строки (но не наоборот) –
поскольку mysql всегда будет преобразовывать ваши данные в соответствующий тип. Единственный известный мне случай – это предложение LIMIT, в котором вы не можете форматировать число как строку, поэтому единственным связанным случаем является тот, когда PDO установлен в режиме эмуляции, и вы должны передать параметр в предложении LIMIT . Во всех остальных случаях вы можете опустить третий параметр, а также явный вызов bindValue()
без каких-либо проблем.
Вы должны обязательно использовать API prepare
и передавать значения отдельно от запроса, в отличие от простой интерполяции строк (например, "SELECT * FROM foo WHERE bar = '$baz'"
→ плохо ).
Для параметров привязки у вас есть три варианта:
bindParam
bindValue
execute
Неважно, какой из них вы используете, все они одинаково безопасны. См. Ответы на некоторые подробности о различиях:
При использовании bindParam
или bindValue
передача третьего аргумента типа PDO::PARAM_
является необязательной. Если вы его не передадите, по умолчанию используется привязка аргумента как строки. Это означает, что вы можете получить эквивалентный запрос ... WHERE foo = '42'
вместо ... WHERE foo = 42
. Это зависит от вашей базы данных, как она справится с этим. MySQL будет автоматически вводить строку в число, как это делает PHP (например, в '42' + 1
). Другие типы баз данных могут быть более суетливыми в отношении типов.
Опять же, все варианты одинаково безопасны. Если вы пытаетесь связать строку 'foo'
с помощью PDO::PARAM_INT
, строка будет отлита к целому числу и, соответственно, привязана как значение 0
. Нет возможности для инъекций.
Да, вы всегда должны связывать params с подготовленным оператором. Это более безопасно и ограничивает SQL-инъекцию. Но это не единственное, что нужно сделать для запроса параметров: необходим правильный тип управления, лучше всего, если вы сопоставляете строку с объектом и генерируете исключение, если оно имеет недопустимые данные.
Надеюсь, я могу быть полезен!
Да , привязка – это путь. Или параметризованные запросы, которые имеют более обобщенный термин.
@Theo делает замечательную работу, объясняя, почему параметризованные запросы – это способ пойти
Вы также можете использовать хранимые процедуры для дополнительной безопасности, но это более убитое, если у вас есть одно приложение в одной базе данных. Он хорош для нескольких приложений в одной базе данных, чтобы обеспечить согласованность при обработке данных