2010-09-10 4 views
35

En un servidor anterior que estoy usando no puedo usar declaraciones preparadas. Actualmente estoy intentando escapar por completo de la entrada del usuario antes de enviarlo a MySQL. Para esto estoy usando la función PHP mysql_real_escape_string.Escapar tarjetas alocadas de MySQL

Dado que esta función no escapa a los comodines de MySQL% y _ Estoy usando addcslashes para escapar de estos también.

Cuando envío algo como:

test_test " ' 

a la base de datos y luego leer de nuevo la base de datos de muestra:

test\_test " ' 

En cuanto a esto no puedo entender por qué el _ tiene un precedente barra diagonal inversa, pero el "y" no. Dado que todos están escapados con \ seguramente _ 'y "todos deben aparecer iguales, es decir, todos tienen el carácter de escape visible o todos no lo tienen visible.

escape que son los \ T proyectarán de forma automática por

¿Alguien puede explicar esto?

Respuesta

79

_ y % no son comodines en MySQL en general, y no se deben escapar con el propósito de ponerlos en literales de cadena normales. mysql_real_escape_string es correcto y suficiente para este propósito. addcslashes no debe ser utilizado.

_ y % son especiales únicamente en el contexto de LIKE-emparejamiento. Cuando desee preparar cadenas para uso literal en una declaración LIKE, para que 100% coincida con el cien por ciento y no con cualquier cadena que comience con cien, tiene dos niveles de escape de los que preocuparse.

El primero es LIKE escaping. ¡El manejo de LIKE ocurre completamente dentro de SQL, y si desea convertir una cadena literal en una expresión LIKE literal, debe realizar este paso , incluso si está utilizando consultas parametrizadas!

En este esquema, _ y % son especiales y se deben escapar. El personaje de escape también debe ser escapado. De acuerdo con ANSI SQL, los caracteres distintos de estos no deben escaparse: \' sería incorrecto. (Aunque MySQL normalmente le permitirá salirse con la suya.)

Habiendo hecho esto, procederá al segundo nivel de escape, que es el antiguo escape literal de cadena antigua. Esto se lleva a cabo fuera de SQL, creando SQL, así que debe hacerse después del paso de escape LIKE. Para MySQL, esto es mysql_real_escape_string como antes; para otras bases de datos habrá una función diferente, puede usar consultas parametrizadas para evitar tener que hacerlo.

¡El problema que lleva a confusión aquí es que en MySQL usa una barra invertida como un carácter de escape para los dos pasos de escape anidados! Entonces, si quisieras hacer coincidir una cuerda con un signo de porcentaje literal, tendrías que hacer una doble barra invertida: escapar y decir LIKE 'something\\%'. O, si eso está en un literal PHP " que también usa el escape de barra invertida, "LIKE 'something\\\\%'". Argh!

Esto es incorrecto de acuerdo con ANSI SQL, que dice que: en literals de cadena, las barras invertidas significan barras invertidas literales y la forma de escapar de una sola cita es ''; en expresiones LIKE no hay ningún carácter de escape por defecto.

Así que si quiere LIKE-escapar de forma portátil, debe anular el comportamiento predeterminado (incorrecto) y especificar su propio carácter de escape, utilizando el constructo LIKE ... ESCAPE .... ¡Para la sensatez, elegiremos algo más que la maldita barra invertida!

function like($s, $e) { 
    return str_replace(array($e, '_', '%'), array($e.$e, $e.'_', $e.'%'), $s); 
} 

$escapedname= mysql_real_escape_string(like($name, '=')); 
$query= "... WHERE name LIKE '%$escapedname%' ESCAPE '=' AND ..."; 

o con parámetros (por ejemplo, en DOP.):

$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ..."); 
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR); 

(Si quieres que el tiempo del partido más portabilidad, también puede divertirse tratando de dar cuenta de MS SQL Server y Sybase, donde el El carácter [ también es, incorrectamente, especial en una declaración LIKE y tiene que ser escapado. Argh.)

+4

¡Volvería a hacer +1 por "la maldita barra invertida!". – BoltClock

+0

Gracias, acaba de absorber esto ahora ... esto realmente me está ayudando a ampliar mis conocimientos básicos. Estúpidamente, estaba escapando% y _ aunque en realidad no estoy usando ninguna declaración LIKE y como creo que (por favor confirma) que% y _ son solo comodines en el contexto de una declaración LIKE, de hecho estoy perdiendo el tiempo. Pero eso me hace pensar por qué querrías escapar de un% o _ cuando está en el contexto de una declaración LIKE. Seguramente la única razón para usar una declaración LIKE es para poder usar sus comodines. (Disculpe mi conocimiento limitado sobre esto) – Columbo

+2

Claro, pero es perfectamente natural querer buscar un carácter literal '%' o '_'. Si un usuario busca '50%' en el front-end, probablemente signifiquen que están buscando una cadena que contenga '50%' y no cualquier cadena con '50' en ella. – bobince

Cuestiones relacionadas