PHP Подготовленные заявления
Подготовленные операторы очень полезны для SQL-инъекций.
Подготовленные операторы и связанные параметры
Подготовленный оператор — это функция, используемая для выполнения одних и тех же (или аналогичных) инструкций SQL многократно с высокой эффективностью.
Подготовленные заявления в основном работают так:
- Подготовка: шаблон инструкции SQL создается и отправляется в базу данных. Некоторые значения остаются неопределенными, называются параметрами (помеченными как "?"). Пример: Вставка в значения мигуестс (?,?,?)
- База данных анализирует, компилирует и выполняет оптимизацию запросов в шаблоне инструкции SQL и сохраняет результат без его выполнения
- Выполнить: в более позднее время приложение привязывает значения к параметрам, и база данных выполняет инструкцию. Приложение может выполнять инструкцию столько раз, сколько она хочет, с различными значениями
По сравнению с выполнением инструкций SQL напрямую, подготовленные операторы имеют три основных преимущества:
- Подготовленные операторы сокращают время синтаксического анализа, поскольку подготовка запроса выполняется только один раз (хотя инструкция выполняется несколько раз)
- Привязанные параметры минимизируют пропускную способность сервера, так как необходимо отправлять только параметры каждый раз, а не весь запрос
- Подготовленные операторы очень полезны для SQL-инъекций, поскольку значения параметров, которые передаются позже с использованием другого протокола, не должны быть корректно экранированы. Если исходный шаблон инструкции не является производным от внешнего входа, внедрение SQL не может произойти.
Подготовленные заявления в mysqli
В следующем примере используются подготовленные операторы и связанные параметры в mysqli:
Пример (mysqli с подготовленными заявлениями)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "Html";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
Строки кода, поясняющие пример выше:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
В нашем SQL, мы вставляем вопросительный знак (?) где мы хотим заменить в целочисленном, строковом, двойном или значении BLOB.
Затем, посмотрите на функцию бинд_парам ():
$stmt->bind_param("sss", $firstname, $lastname, $email);
Эта функция связывает параметры с SQL-запросом и сообщает базе данных о параметрах. В аргументе "SSS" перечислены типы данных, которые являются параметрами. Символ s указывает MySQL, что параметр является строкой.
Аргумент может быть одним из четырех типов:
- i - Целое число
- d - Двухместный
- s - Строка
- b - BLOB
Мы должны иметь один из них для каждого параметра.
Говоря MySQL, какой тип данных следует ожидать, мы минимизируем риск инъекций SQL.
Примечание: Если мы хотим вставить какие-либо данные из внешних источников (например, ввод данных пользователем), очень важно, чтобы данные были очищены и проверены.
Подготовленные заявления в PDO
В следующем примере используются подготовленные операторы и связанные параметры в PDO:
Пример (PDO с подготовленными заявлениями)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);
// insert a row
$firstname = "Html";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>