filter_var - filtros de validacion php
php: ¿es FILTER_SANITIZE_EMAIL sin sentido? (4)
Aquí es cómo insertar sólo 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 funciones valiosas y tienen diferentes usos.
La validación está probando si el correo electrónico es un formato válido. Desinfectar es limpiar los caracteres malos 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.
Fuente para 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 "!#$%&''*+-=?^_`{|}~@.[]";
filter_map map;
filter_map_init(&map);
filter_map_update(&map, 1, allowed_list);
filter_map_apply(value, &map);
}
Fuente para 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
}
}
Estoy creando un formulario de registro y solo busco insertar correos electrónicos válidos y seguros en la base de datos.
Varios sitios (incluyendo w3schools) recomiendan ejecutar FILTER_SANITIZE_EMAIL antes de ejecutar FILTER_VALIDATE_EMAIL para estar seguros; sin embargo, esto podría cambiar el correo electrónico enviado de un inválido a un correo electrónico válido, que no podría ser lo que el usuario deseaba, por ejemplo:
El usuario tiene la dirección de correo electrónico [email protected], pero accidentalmente inserta jeff "@ gmail.com.
FILTER_SANITIZE_EMAIL eliminaría "haciendo que el correo electrónico [email protected] lo que FILTER_VALIDATE_EMAIL diría que es válido aunque no sea la dirección de correo electrónico del usuario.
Para evitar este problema, solo planeo ejecutar FILTER_VALIDATE_EMAIL. (Suponiendo que no pretendo enviar / procesar ningún correo electrónico declarado no válido)
Esto me dirá si el correo electrónico es válido o no. Si es así, no debería haber necesidad de pasarlo a través de FILTER_SANITIZE_EMAIL porque cualquier carácter ilegal / inseguro, ya habría hecho que el correo electrónico fuera devuelto, ¿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 los espacios en blanco, paréntesis () y punto y coma invalidarán el correo electrónico. ¿O me equivoco?
(nota: usaré declaraciones preparadas para insertar los datos además de esto, solo quería aclarar esto)
La forma "correcta" de hacerlo es solicitando el correo electrónico del usuario dos veces (lo cual 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.
Debe comprender que un filtro que validates devuelve true
o false
mientras que un filtro que sanitizes realidad modifica la variable dada. Los dos no sirven el mismo propósito.
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 simplemente ignorarlo. La solución, creo, es comparar el original con la versión desinfectada. Es decir, para usar el ejemplo de w3schools, simplemente añada:
$cleanfield=filter_var($field, FILTER_SANITIZE_EMAIL);
if($cleanfield != $field){
return FALSE;
}
No reinvente la rueda, deje que su servidor de correo haga el trabajo: la verificación / validación adecuada del correo electrónico es un asunto demasiado complejo para hacerlo todo a mano. Por ejemplo, los correos electrónicos válidos pueden, de hecho, contener espacios según RFC2822. Ni siquiera mencionar IDN .
Escape toda la salida para estar seguro de XSS. Escapar de los parámetros de SQL como de costumbre. Utilizar consultas preparadas. Si escapa adecuadamente todas sus entradas y salidas, no importa lo que guarde en una base de datos, por lo tanto, desinfectar este tipo de datos no tiene sentido.
Línea de fondo:
- Revise los correos electrónicos sólo para ver si hay corrección básica.
- use
FILTER_VALIDATE_EMAIL
si tiene que hacerlo, - no utilice
FILTER_SANITIZE_EMAIL
para los datos enviados por el usuario.
(Creo que vale la pena señalar que en algunas versiones anteriores de PHP FILTER_VALIDATE_EMAIL
no FILTER_VALIDATE_EMAIL
bien en un sitio web típico de Internet: le dirá que john@gmail
es un correo electrónico válido).