Les instructions préparées sont très utiles pour empêcher l'injection MySQL.
Instructions préparées et paramètres liés
Les instructions préparées sont utilisées pour exécuter plusieurs instructions SQL identiques avec une efficacité d'exécution plus élevée.
Les instructions de prétraitement fonctionnent comme suit :
1. Prétraitement : créez un modèle d'instruction SQL et envoyez-le à la base de données. Les valeurs réservées sont marquées du paramètre "?". Par exemple :
INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
2. Analyse de la base de données, compilation, optimisation des requêtes sur les modèles d'instructions SQL et stockage des données. résultats Aucune sortie.
3. Exécution : Enfin, la valeur liée à l'application est transmise au paramètre (marque "?") et la base de données exécute l'instruction. L'application peut exécuter l'instruction plusieurs fois si les valeurs des paramètres sont différentes.
Par rapport à l'exécution directe d'instructions SQL, les instructions préparées présentent deux avantages principaux :
1) Les instructions préparées réduisent considérablement le temps d'analyse et n'effectuent qu'une seule requête (bien que les instructions soient implémentées plusieurs fois).
2) Les paramètres de liaison réduisent la bande passante du serveur, il vous suffit d'envoyer les paramètres de la requête au lieu de l'intégralité de l'instruction.
Les instructions préparées sont très utiles pour l'injection SQL, car différents protocoles sont utilisés après l'envoi des valeurs des paramètres, garantissant la légitimité des données.
Instructions préparées MySQLi
Les exemples suivants utilisent des instructions préparées dans MySQLi et lient les paramètres correspondants :
Exemple (MySQLi utilise des instructions préparées)
<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // 创建连接 $conn = new mysqli($servername, $username, $password, $dbname); // 检测连接 if ($conn->connect_error){ die("连接失败: " . $conn->connect_error); } // 预处理及绑定 $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"); $stmt->bind_param("sss", $firstname, $lastname, $email); // 设置参数并执行 $firstname = "John"; $lastname = "Doe"; $email = "john@example.com"; $stmt->execute(); $firstname = "Mary"; $lastname = "Moe"; $email = "mary@example.com"; $stmt->execute(); $firstname = "Julie"; $lastname = "Dooley"; $email = "julie@example.com"; $stmt->execute(); echo "新记录插入成功"; $stmt->close(); $conn->close(); ?>
Analyse chaque ligne de code pour l'exemple suivant :
"INSERT INTO MyGuests (prénom , nom, email) VALEURS(?, ?, ?)"
Dans l'instruction SQL, nous avons utilisé le point d'interrogation (?), ici nous pouvons remplacer le point d'interrogation par des entiers, des chaînes, des doubles , et les booléens.
Ensuite, jetons un coup d'œil à la fonction bind_param() :
$stmt->bind_param("sss", $firstname, $lastname, $email);
Cette fonction lie les paramètres SQL et indique à la base de données la valeur des paramètres. La colonne de paramètres "sss" gère les types de données des paramètres restants. Le caractère s indique à la base de données que le paramètre est une chaîne.
Les paramètres ont les quatre types suivants :
i - entier (type entier)
d - double (type à virgule flottante double précision)
s - string (string)
b - BLOB (grand objet binaire : grand objet binaire)
Chaque paramètre doit spécifier le type.
Vous pouvez réduire le risque d'injection SQL en indiquant à la base de données le type de données du paramètre.
Remarque : Si vous souhaitez insérer d'autres données (saisie de l'utilisateur), la validation des données est très importante.
Instructions préparées dans PDO
Dans les exemples suivants, nous utilisons des instructions préparées et des paramètres de liaison dans PDO :
Exemple (PDO utilisant des instructions préparées)
<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; try { $conn = new PDO("mysql:host=$servername; dbname=$dbname", $username, $password); // 设置 PDO 错误模式为异常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 预处理 SQL 并绑定参数 $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); // 插入行 $firstname ="John"; $lastname = "Doe"; $email = "john@example.com"; $stmt->execute(); // 插入其他行 $firstname = "Mary"; $lastname = "Moe"; $email = "mary@example.com"; $stmt->execute(); // 插入其他行 $firstname = "Julie"; $lastname = "Dooley"; $email = "julie@example.com"; $stmt->execute(); echo "新记录插入成功"; } catch(PDOException $e) { echo $sql . "<br>" . $e->getMessage(); } $conn = null; ?>