No, no es así, use declaraciones preparadas como está más una sola consulta Funciones y correcta validación de entrada. El último es el predeterminado para la mayoría de las funciones en PHP (por ejemplo, mysqli::query
Vs. mysqli::multi_query
).
Declaraciones preparadas
Las declaraciones preparadas enviarán los datos de una variable y su tipo por separado a su DBMS, que a su vez escapará a todos los caracteres ofensivos en su nombre o analizará los datos independientemente de la consulta real (según el DBMS). No hay nada que saber sobre qué personajes deben ser escapados y cuáles no. Esta es la forma más segura de lograrlo.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(null, null, null, "database");
$mysqli->prepare("SELECT * FROM 'users' WHERE 'id' = ?");
$mysqli->bind_param("d", $_GET["id"]);
$mysqli->execute();
// ...
Toda esta complejidad se puede abstraer, eche un vistazo, por ejemplo, a Código fuente de Drupal.
Funciones de consulta únicas
Las funciones de consulta única aseguran que una consulta tuya siempre solo producirá una consulta única que se pasará al DBMS. Eliminando efectivamente cualquier posibilidad de que alguien termine su consulta y ejecute otra; un escenario típico con inyección SQL, ejemplo:
<?php
$_GET["id"] = "1;SET foreign_key_checks=0;DROP TABLE users";
$mysqli->multi_query("SELECT * FROM 'users' WHERE 'id' = {$_GET["id"]}");
Validación
Este es quizás el consejo más importante y siempre es importante, no importa lo que intentes lograr. Use las filter_*
funciones integradas de PHP y verifique otros proyectos grandes para validar cosas que no están cubiertas por estas funciones.
Ejemplo combinado
Vamos a ponerlo todo junto.
<?php
// max_range default is PHP_INT_MAX.
$userId = filter_input(INPUT_GET, "id", FILTER_VALIDATE_INT, array(
"options" => array("min_range" => 1),
));
// Contains either a valid integer now or either FALSE or NULL.
if ($userId === null || $userId === false) {
//if (!$userId) {
throw new \InvalidArgumentException();
}
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(null, null, null, "database");
$stmt = $mysqli->prepare("SELECT 'name' FROM 'users' WHERE 'id' = ?");
%stmt->bind_param("d", $userId);
$stmt->execute();
$stmt->fetch($userName);
$stmt->close();
$mysqli->close();
exit("Hello {$userName} with {$userId}.");