MySQLI :: STMT_INIT est une méthode dans l'extension PHP MySQLI qui est utilisée pour initialiser une instruction préparée. Les instructions préparées sont un mécanisme pour exécuter des requêtes SQL, qui peuvent séparer les requêtes SQL des variables saisies par les utilisateurs, évitant efficacement les attaques d'injection SQL. Grâce à cette méthode, le développeur peut d'abord créer un objet d'instruction vide, lier des paramètres et les exécuter dans les opérations suivantes.
Le principe de l'attaque par injection SQL est que l'attaquant injecte du code SQL malveillant dans les champs entrés par l'utilisateur (tels que le nom d'utilisateur, le mot de passe, etc. du formulaire de connexion), et le fine directement dans la requête SQL d'une manière inappropriée. De cette façon, l'attaquant peut modifier l'instruction SQL d'origine pour effectuer des opérations malveillantes. Pour éviter cela, MySQLI fournit des instructions préparées et des paramètres de liaison.
Avec l'aide de MySQLI :: STMT_INIT , les développeurs peuvent éviter l'injection SQL via les étapes suivantes:
Structure et données de requête séparées: MySQLI :: STMT_INIT est utilisée pour initialiser un modèle de requête SQL, où la structure de requête est fixe et les données d'entrée réelles sont transmises à la base de données via la liaison des paramètres. Cela signifie que toutes les données entrées par l'utilisateur ne sont pas épissées directement avec l'instruction SQL, mais sont transmises à la base de données en tant que paramètre.
Paramètres de liaison: via la méthode bind_param , les développeurs peuvent lier l'entrée de l'utilisateur aux paramètres de la requête SQL. Ces données d'entrée sont traitées et échappées par le serveur MySQL pour s'assurer qu'elles ne sont pas exécutées sous forme de code SQL. Par exemple, les chaînes seront automatiquement citées et les nombres seront traités de manière appropriée. De cette façon, même si l'utilisateur entre dans le code SQL malveillant, il ne peut pas affecter l'exécution de la requête.
Exécuter la requête: la requête ne sera exécutée qu'après que tous les paramètres sont liés. De cette façon, même si l'utilisateur entre une chaîne contenant du code d'injection SQL, l'intégralité de l'instruction de requête ne sera pas falsifiée, assurant la sécurité des données.
Avec MySQLI :: STMT_INIT et les déclarations de prétraitement, nous pouvons réduire fondamentalement le risque d'attaques d'injection SQL. Voici les étapes pour y parvenir:
Instruction d'initialisation: utilisez mysqli :: stmt_init pour créer un objet de déclaration de prétraitement vide.
$conn = new mysqli('localhost', 'username', 'password', 'database');
$stmt = $conn->stmt_init();
Préparez la requête SQL: utilisez la méthode de préparation pour créer un modèle de déclaration SQL préparé. Notez que la pièce d'entrée de l'utilisateur dans la requête SQL utilise à la place les espaces réservés (par exemple ? ).
$sql = "SELECT * FROM users WHERE username = ? AND password = ?";
if ($stmt->prepare($sql)) {
// Opération supplémentaire
}
Paramètres de liaison: utilisez la méthode bind_param pour lier la valeur d'entrée utilisateur avec l'espace réservé dans le modèle de requête SQL. Le deuxième paramètre de cette méthode représente le type de paramètre, comme S représente une chaîne, je représente un entier, etc.
$stmt->bind_param('ss', $username, $password);
Exécuter Query: Enfin, la requête SQL avec des paramètres à exécuter via la méthode EXECUTE .
$stmt->execute();
De cette façon, la saisie de l'utilisateur dans les requêtes SQL sera toujours traitée comme des données plutôt que du code SQL, évitant ainsi les attaques d'injection SQL.
Voici un exemple pratique qui montre comment empêcher l'injection SQL à l'aide de mysqli :: stmt_init :
<?php
$conn = new mysqli('localhost', 'username', 'password', 'database');
// Vérifiez si la connexion réussit
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Obtenez la saisie des utilisateurs
$username = $_POST['username'];
$password = $_POST['password'];
// Initialiser les déclarations de prétraitement
$stmt = $conn->stmt_init();
if ($stmt->prepare("SELECT * FROM users WHERE username = ? AND password = ?")) {
// Lier les paramètres
$stmt->bind_param('ss', $username, $password);
// Exécuter une requête
$stmt->execute();
// Obtenir des résultats
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "Connectez-vous avec succès!";
} else {
echo "Nom d'utilisateur ou mot de passe non valide。";
}
// Déclaration étroite
$stmt->close();
}
// Fermer la connexion
$conn->close();
?>
Dans cet exemple, même si l'entrée utilisateur contient du code malveillant (comme l'administrateur 'ou' 1 '=' 1 ), l'entrée n'affecte pas la structure de la requête SQL, car elle est traitée comme un paramètre.