Haz todo lo posible por entender el código bien antes de utilizarlo a tu proyecto y si tdeseas aportar algo puedes dejarlo en los comentarios.
Solución:
Ahora, suponiendo que esas 4 variables fueron ingresadas por el usuario, no entiendo cómo esto evita las inyecciones de SQL. Según tengo entendido, todavía pueden ingresar lo que quieran allí.
El principio principal es usar una declaración preparada que está diseñada para enviar consultas seguras al servidor de db, esto se puede hacer escapando de la entrada del usuario que no es parte de la consulta real, y también verificando la consulta sin ninguna (cláusula where) para verificar el validez de la consulta antes de usar cualquier parámetro.
De esta pregunta: PDO envía una consulta sin procesar a MySQL mientras que Mysqli envía una consulta preparada, ambas producen el mismo resultado
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) {
$stmt->bind_param("i", $user);
$user = "''1''";
registros del servidor:
130802 23:39:39 175 Connect ****@localhost on testdb
175 Prepare SELECT * FROM users WHERE username =?
175 Execute SELECT * FROM users WHERE username =0
175 Quit
Al usar la declaración preparada, el servidor de base de datos verificará la consulta sin ningún parámetro, en esta etapa, se pueden detectar errores antes de vincular cualquier parámetro, luego, si la consulta fue válida, los parámetros también se enviarán al servidor para finalizar la consulta.
Del manual de PHP http://php.net/manual/en/mysqli.quickstart.prepared-statements.php:
Escape e inyección SQL
Las variables enlazadas serán escapadas automáticamente por el servidor. El servidor inserta sus valores escapados en los lugares apropiados en la plantilla de declaración antes de la ejecución. Se debe proporcionar una sugerencia al servidor para el tipo de variable enlazada, para crear una conversión adecuada. Consulte la función mysqli_stmt_bind_param() para obtener más información.
..
Tampoco puedo encontrar una explicación para el ‘sssd’ allí. ¿Qué hace? ¿Es eso lo que lo hace más seguro?
La respuesta está aquí: http://php.net/manual/en/mysqli-stmt.bind-param.php
i
corresponding variable has type integer
d
corresponding variable has type double
s
corresponding variable has type string
b
corresponding variable is a blob and will be sent in packets
Pregunta final: leí en otra pregunta que mysqli_real_escape_string está en desuso, pero no dice eso en el manual. ¿Cómo está en desuso? ¿Ya no puede escapar de los caracteres especiales por alguna razón?
¿Puedes dar una referencia? Creo que lo entendiste mal con (mysql_real_escape_string()
)
Al usar declaraciones preparadas, está separando las consultas SQL de los datos ingresados por el usuario. En lugar de datos de entrada, coloca marcadores de posición (‘?’ char) en su consulta SQL. Luego envía la consulta al servidor DBMS (por ejemplo: MySQL) mediante el método “mysqli::prepare”. Entonces, el servidor verifica que todo esté bien y, si es así, espera los datos de entrada. A estas alturas ya conoce tu consulta. Solo tiene que esperar a que los datos de entrada se vinculen a la consulta.
En este punto, “bind_param” entra en acción, vinculando marcadores de posición a los datos ingresados por el usuario. Darse cuenta de bind_param solo vincula datos a marcadores de posición sin modificar la consulta. Por lo tanto, no hay forma de cambiar la consulta SQL original, porque ya se envió al servidor mediante el método de preparación y porque está enviando consultas SQL y datos de entrada por separado para que los datos ingresados por el usuario no interfieran con las consultas.
DE TODOS MODOS…
El propósito real de usar una declaración preparada en SQL es reducir el costo de procesar consultas, NO separar los datos de la consulta. Así es como se usa ahora, no como fue diseñado para ser usado en primer lugar.
‘sssd’ significa “string”, “string”, “string” y “doble”. De hecho: $code es un string$lenguaje es un string$oficial es un string y $percent es un tipo doble.
mysqli_real_escape_string no está en desuso, pero mysql_real_escape_string sí lo está (el primero es mysqlI, donde I significa “mejorado”).