2010-01-10 22 views
6

PDO y las declaraciones preparadas todavía me confunden un poco, sin importar lo mucho que las haya leído hasta ahora. Entonces sé que son más "seguros", pero, ¿es realmente tan importante? Quiero decir que puedo obtener el mismo resultado final utilizando mysql básico con mysql_real_escape_string() y htmlspecialchars() ¿no?¿Debería estar realmente usando PDO y declaraciones preparadas?

Respuesta

10

Podría, pero las declaraciones preparadas y PDO son absolutamente seguras. ¿Podría hacerlo a mano y usar la función mysql_real_escape_string()? Por supuesto. De hecho, su salida puede parecer idéntica. Pero al final, el código que PDO requeriría sería muchísimo más corto que el código si lo hubiera hecho manualmente.

Además, si no está utilizando declaraciones preparadas, corre el riesgo de error humano: digamos que se olvidó de escapar un valor o desinfectar una entrada. Mezclado con todos sus otros códigos, la única línea que no se desinfecta correctamente podría convertirse en una pesadilla en el futuro.

Espero que esto ayude!

+0

"las declaraciones preparadas son absolutamente seguras", "su salida puede parecer idéntica" - ¿Qué? ¡¿Por qué?! Las declaraciones preparadas son tan seguras como usar 'mysql_real_escape_string()' y la salida siempre se verá idéntica. –

+0

Alix: hay menos posibilidades de error humano. Si siempre escapa de todo correctamente (es decir, PDO) porque la única forma en que está cargando datos en una consulta es a través de una función de escape, entonces se le garantiza que la información es 100% sanitaria. Y no, la salida no siempre se verá idéntica. Los estilos de citas, los estilos de escape y la compatibilidad con los tipos de datos variarán según el enfoque que elija. – mattbasta

0

Siempre y cuando desinfecte los datos apropiadamente para sus consultas, entonces no tiene para usar declaraciones preparadas/PDO. Aunque, yo personalmente recomendaría usar declaraciones preparadas/PDO simplemente porque ambas facilitan el desarrollo/la depuración y las declaraciones preparadas evitan que los tipos de datos incorrectos entren incluso en una consulta.

Si desea obtener más información acerca de cómo crear una instrucción preparada simple, busque en la función sprintf. Simplemente reemplaza cualquier cadena de variables, enteros, etc. con un especificador de tipo (en este caso %s y %d respectivamente). Por ejemplo, en la siguiente consulta, sé que id va a ser un número entero (será numérico) y name será una cadena (alfanumérica).

$username = 'Simon'; 
$id  = 3; 
$query = "SELECT FROM `users` WHERE `id` = {$id} AND `name` = '{$username}'"; 

Si estoy recibiendo ninguna de estas variables a partir de una fuente no fiable (como un POST/GET) entonces puedo asegurarse de que son los tipos de datos correctos mediante la sustitución de la línea final ($ consulta set) con una llamada sprintf así:

$username = 'Simon'; 
$id  = 3; 
$query = sprintf("SELECT FROM `users` WHERE `id` = %d AND `name` = '%s'", $id, $username); 

sprintf simplemente no me deja utilizar una cadena para el $ id o un número entero para el nombre $ cuando se le llama, que asegura los tipos correctos de los datos se ofrecen (esto me da un poco más de seguridad). SI se dan tipos de datos incorrectos, entonces creo que convertirá las variables al tipo solicitado.

Para leer más sobre sprintf visita aquí: http://php.net/sprintf

espero que esto explica lo suficiente (es mi primera respuesta) :).

+1

He visto el sprintf() utilizado anteriormente en cosas como wordpress, vbulletin y otros códigos conocidos. En su ejemplo, $ query se ejecutará en una función regular de mysql? Me doy cuenta de que sprintf() es más seguro, pero tengo curiosidad, ¿se lo considera una verdadera "declaración preparada" o simplemente una técnica similar? Gracias – JasonDavis

+2

Sin embargo, no desinfectará su SQL por usted. Ese código no funcionará. Terminará con '... AND \' name \ '= Simon'-no agregó las comillas alrededor de" Simon ", y' sprintf' definitivamente no lo hará por usted. –

+0

Sí, ejecutaría esto a través de su función de consulta MySQL relevante (mysql_query() si está utilizando el controlador estándar). No estoy seguro de si consideraría sprintf como una declaración realmente preparada, pero al menos está lo suficientemente cerca :-) @Samir: Disculpas, eliminé el 'por un error. ¡Gracias por mencionarlo! +1 – Simon

0

puede probar zend_db que usa pdo debajo del capó. (mdb2 es otra opción que puede usar.)

+0

Zend_Db tiene adaptadores para muchas extensiones PDO, así como algunas extensiones no PDO, pero no MDB2. –

+0

sí, quiero decir como otro dbi que el OP podría intentar ... – jspcal

3

Me gusta mucho la interfaz PDO. Una vez que te acostumbras, es mucho más limpio que el estilo de función mysql_ *. Me tomó un tiempo darme cuenta, también, pero vale la pena.

La parte que encontré confusa fue recordar qué métodos pertenecen al objeto de conexión PDO DB, y cuáles son parte de los objetos de declaración.

Con ciertas acciones, obtendrá un beneficio de rendimiento al repetir declaraciones preparadas también. Por ejemplo, si está haciendo un montón de insertos en un bucle, puede preparar el enunciado y luego enlazar los datos nuevos en el bucle cada vez antes de insertarlos.

La seguridad es mucho mejor también, ya que confía en una biblioteca bien probada para escapar de sus datos en cada inserción. Es como la criptografía. ¿Por qué lo haces tú mismo cuando es algo tan importante? No hay ninguna razón para darse la oportunidad de equivocarse (es decir, perder accidentalmente algo que se escapó de una consulta).

Recomiendo this guide a PDO, del autor que escribió esto excellent giant book on Mysql.

me gusta usar el estilo de parámetro de posición, y luego simplemente hacer una matriz de los datos y transmitirlo. Mis consultas parecen

$pdo_db=pdo_connect('cow_db'); 
$sql='select this,that,count(those) as snout from lovely_table where name=? and horses=?'; 
$data=array($username,$horse_count); 

$query_stmt=$pdo_db->prepare($sql); 
$result_handle=$query_stmt->execute($data); 

//then I have a function to load data from the result handle 
$info=load_array($result_handle); 

Se podría hacer funciones como este para trabajar con la norma interfaz php mysql, pero ¿por qué no usar PDO?

+0

+1, también me encanta el estilo del parámetro posicional. –

2

Estoy de acuerdo con otros que dicen que usar consultas preparadas es generalmente mejor que usar funciones de escape. Es más fácil de usar correctamente, y no hay forma de que los valores de los parámetros puedan presentar problemas de inyección de SQL, ya que el valor se envía al servidor RDBMS de forma separada de la consulta SQL.

Sin embargo, el uso de parámetros es útil solo cuando las partes dinámicas de su consulta SQL son un parámetro en lugar de un valor literal en una expresión. No puede usar un parámetro de consulta en lugar de un nombre de tabla, un nombre de columna, una expresión SQL o una lista de valores (por ejemplo, argumentos de un predicado IN()).

Las consultas preparadas también tienen mejor rendimiento que las consultas no preparadas (al menos en MySQL). La mayoría de la gente dice lo contrario, pero el mysqlperformanceblog.com respetado hicieron las pruebas:

http://www.mysqlperformanceblog.com/2006/08/02/mysql-prepared-statements/

0

PHP le permite hacer cualquier cosa que desee, y da la casualidad de PDO no lo que "quiere" con mucha menos código :)

Cuestiones relacionadas