2011-09-03 14 views
17

Solo estoy creando un formulario de registro y estoy buscando solo insertar correos electrónicos válidos y seguros en la base de datos.php - ¿No tiene sentido FILTER_SANITIZE_EMAIL?

Varios sitios (incluyendo w3schools) recomienda ejecutar FILTER_SANITIZE_EMAIL antes de ejecutar FILTER_VALIDATE_EMAIL para estar seguro, sin embargo, esto podría cambiar el correo electrónico enviado desde un inválido en un correo electrónico válida, que no podría ser lo que el usuario desea, por ejemplo:

usuario tiene correo electrónico [email protected], pero accidentalmente inserta Jeff "@ gmail.com.

FILTER_SANITIZE_EMAIL eliminaría la" haciendo el correo electrónico [email protected] la que diría FILTER_VALIDATE_EMAIL es válida a pesar de que no son los usuarios dirección de correo electrónico real

Para evitar este problema, planeo ejecutar solo FILTER_VALIDATE_EMAIL. (suponiendo que no planeo sacar/procesar ningún correo electrónico declarado inválido)

Esto me dirá si el correo electrónico es válido, si es así, entonces no debería haber necesidad de pasarlo por FILTER_SANITIZE_EMAIL porque cualquier ilegal/los caracteres inseguros, ya hubieran causado que el correo electrónico devuelto no sea válido, ¿correcto?

Tampoco conozco ningún correo electrónico aprobado como válido por FILTER_VALIDATE_EMAIL que pueda usarse para inyección/xss debido a que espacios en blanco, paréntesis() y punto y coma invalidarán el correo electrónico. ¿O estoy equivocado?

(nota: Me va a utilizar declaraciones preparadas para insertar los datos, además de esto, sólo quería aclarar esto)

+0

etiqueta de inyección SQL eliminado –

+0

Por lo tanto, todas las respuestas de abajo es de hecho demostrado FILTER_SANITIZE_EMAIL es de hecho inútil, ya que sólo puede utilizar FILTER_VALIDATE_EMAIL solo. –

Respuesta

4

La forma "correcta" de hacer esto es pedir por correo electrónico del usuario dos veces (que es una práctica común/buena). Pero para responder a su pregunta, FILTER_SANITIZE_EMAIL no tiene sentido. Es un filtro que desinfecta los correos electrónicos y hace bien su trabajo.

Es necesario comprender que un filtro que sea validates devuelve true o false mientras que un filtro que sanitizes realidad modifica la variable dada. Los dos hacen no sirven para el mismo propósito.

+2

'Los dos no sirven para el mismo propósito. Que es exactamente lo que se dijo en parte de la pregunta. Esto no aborda lo que se está preguntando. – Izkata

1

No reinvente la rueda, deje que su servidor de correo haga el trabajo: correcto email verification/validation is too complex matter para hacerlo todo a mano. P.ej. Los correos electrónicos válidos pueden, de hecho, contener espacios según RFC2822. Ni siquiera mencionando IDN.

Escapar toda la salida para estar seguro de XSS. Escape de los parámetros de SQL como de costumbre. Use consultas preparadas. Si escapa correctamente a todas sus entradas y salidas, entonces no importa lo que guarde en una base de datos, por lo tanto, desinfectar este tipo de datos no tiene sentido.

En pocas palabras:

  • mensajes de correo electrónico de verificación solamente para la corrección básica,
  • uso FILTER_VALIDATE_EMAIL si tiene que,
  • no utilizan FILTER_SANITIZE_EMAIL para los datos enviados por los usuarios.

(Pensado fuere la pena señalar que en algunas versiones anteriores de PHP FILTER_VALIDATE_EMAIL no hizo bien su trabajo para un sitio web de Internet típico: que te dirá que [email protected] es un email válido.)

+1

Pero 'john @ gmail' es una dirección de correo electrónico válida (gmail podría ser un nombre de máquina conocido localmente). Del mismo modo 'john @ gmail.com' no es válido (los espacios deben ser citados). Entonces el filtro es correcto en ambos. – qbert220

+1

De hecho, es válido, pero uno no debe aceptar el siguiente correo electrónico en un formulario de registro de un sitio web por razones obvias. – sanmai

+0

Acepto que la aceptación de john @ gmail probablemente no sea deseable en un sitio web de Internet. Sin embargo, podría ser perfectamente aceptable en un sitio web de intranet. En su respuesta, parece implicar que el comportamiento de FILTER_VALIDATE_EMAIL es incorrecto. Se devuelve IMO para los 2 casos que da el resultado correcto. Sin embargo, si su uso particular (por ejemplo, que requiera una dirección de correo electrónico global de Internet) es diferente, entonces es posible que desee realizar más comprobaciones (por ejemplo, tal vez busque un "." En la parte que sigue a la "@"). – qbert220

2

Leí el mismo artículo y pensé lo mismo: simplemente cambiar una variable no válida no es suficiente. Necesitamos decirle al usuario que hubo un problema, en lugar de ignorarlo. La solución, creo, es comparar la versión original con la versión desinfectada. Es decir. para usar el ejemplo de w3schools, solo agregue:

$cleanfield=filter_var($field, FILTER_SANITIZE_EMAIL); 
if($cleanfield != $field){ 
return FALSE; 
} 
17

A continuación, se indica cómo insertar solo los correos electrónicos válidos.

<?php 
$original_email = 'jeff"@gmail.com'; 

$clean_email = filter_var($original_email,FILTER_SANITIZE_EMAIL); 

if ($original_email == $clean_email && filter_var($original_email,FILTER_VALIDATE_EMAIL)){ 
    // now you know the original email was safe to insert. 
    // insert into database code go here. 
} 

FILTER_VALIDATE_EMAIL y FILTER_SANITIZE_EMAIL son ambas funciones valiosas y tienen diferentes usos.

La validación está probando si el correo electrónico es un formato válido. Sanitizar es limpiar los caracteres incorrectos del correo electrónico.

<?php 
$email = "[email protected]"; 
$clean_email = ""; 

if (filter_var($email,FILTER_VALIDATE_EMAIL)){ 
    $clean_email = filter_var($email,FILTER_SANITIZE_EMAIL); 
} 

// another implementation by request. Which is the way I would suggest 
// using the filters. Clean the content and then make sure it's valid 
// before you use it. 

$email = "[email protected]"; 
$clean_email = filter_var($email,FILTER_SANITIZE_EMAIL); 

if (filter_var($clean_email,FILTER_VALIDATE_EMAIL)){ 
    // email is valid and ready for use 
} else { 
    // email is invalid and should be rejected 
} 

PHP es de código abierto, por lo que estas preguntas se responden fácilmente con solo usarlo.

Source for FILTER_SANITIZE_EMAIL:

/* {{{ php_filter_email */ 
#define SAFE  "$-_.+" 
#define EXTRA  "!*'()," 
#define NATIONAL "{}|\\^~[]`" 
#define PUNCTUATION "<>#%\"" 
#define RESERVED ";/?:@&=" 

void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL) 
{ 
    /* Check section 6 of rfc 822 http://www.faqs.org/rfcs/rfc822.html */ 
    const unsigned char allowed_list[] = LOWALPHA HIALPHA DIGIT "!#$%&'*+-=?^_`{|}[email protected][]"; 
    filter_map  map; 

    filter_map_init(&map); 
    filter_map_update(&map, 1, allowed_list); 
    filter_map_apply(value, &map); 
}  

Source for FILTER_VALIDATE_EMAIL:

void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ 
{ 
const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD"; 

pcre  *re = NULL; 
pcre_extra *pcre_extra = NULL; 
int preg_options = 0; 
int   ovector[150]; /* Needs to be a multiple of 3 */ 
int   matches; 


/* The maximum length of an e-mail address is 320 octets, per RFC 2821. */ 
if (Z_STRLEN_P(value) > 320) { 
    RETURN_VALIDATION_FAILED 
} 

re = pcre_get_compiled_regex((char *)regexp, &pcre_extra, &preg_options TSRMLS_CC); 
if (!re) { 
    RETURN_VALIDATION_FAILED 
} 
matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3); 

/* 0 means that the vector is too small to hold all the captured substring offsets */ 
if (matches < 0) { 
    RETURN_VALIDATION_FAILED 
} 

} 
+5

'La validación está probando si el correo electrónico es un formato válido. Desinfectar es limpiar los malos caracteres del correo electrónico. 'Esto fue declarado en parte de la pregunta. Esta respuesta no aborda lo que se está preguntando. – Izkata

+1

bien, bastante justo @Izkata. Respuesta actualizada para que pueda insertar solo correos electrónicos válidos. – jbrahy

+2

¿Puede por favor mostrar un ejemplo que muestre claramente cómo la desinfección de un correo electrónico pasaría junto con una validación? Parece que su primer bloque hace que el correo electrónico pase a través SÓLO SI no puede ser desinfectado, o me perdí algo obvio? Y si esto es así, ¿por qué desinfectar en primer lugar? Parece redundante. – BlackBeltScripting

Cuestiones relacionadas