php-est Filtre SANITIZE e-mail inutile?
Je ne fais que créer un formulaire d'inscription, et je ne cherche qu'à insérer des e-mails valides et sûrs dans la base de données.
plusieurs sites (y compris w3schools) recommandent d'exécuter FILTER_SANITIZE_EMAIL avant D'exécuter FILTER_VALIDATE_EMAIL pour être sûr; cependant, cela pourrait changer le courriel soumis d'un non valide en un courriel valide, qui ne pourrait pas être ce que l'utilisateur voulait, par exemple:
l'Utilisateur a l'adresse email jeff!@gmail.com, mais insère accidentellement jeff " @gmail.com.
FILTER_SANITIZE_EMAIL supprimerait le " making the email jeff@gmail.com ce que FILTER_VALIDATE_EMAIL dirait est valide même si ce n'est pas l'adresse e-mail réelle de l'utilisateur.
pour éviter ce problème, Je ne prévois d'exécuter que FILTER_VALIDATE_EMAIL. (en supposant que je n'ai pas l'intention de produire/traiter des e-mails déclarés invalides)
ceci me dira si l'email est valide ou non. S'il l'est, il ne devrait pas être nécessaire de passer à travers FILTER_SANITIZE _EMAIL parce que tout caractère illégal / dangereux, aurait déjà causé le retour de l'email invalide, correct?
Je ne connais pas non plus d'e-mail approuvé comme valide par FILTER_VALIDATE_EMAIL qui pourrait être utilisé pour injection/xss en raison du fait que les espaces blancs, les parenthèses () et les points-virgule invalideraient l'e-mail. Ou je me trompe?
(note: je vais utiliser des déclarations préparées pour insérer les données en plus de cela, je voulais juste clarifier ceci jusqu')
4 réponses
Voici Comment insérer seulement des e-mails valides.
<?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
et FILTER_SANITIZE_EMAIL
sont à la fois des fonctions précieuses et ont des utilisations différentes.
la Validation teste si le courriel est un format valide. Nettoyer est de nettoyer les mauvais caractères hors de l'e-mail.
<?php
$email = "test@hostname.com";
$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 = "test@hostname.com";
$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 est open source, donc il est facile de répondre à ces questions en l'utilisant.
Source pour 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);
}
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
}
}
la" bonne " façon de procéder consiste à demander le courriel de l'utilisateur deux fois (ce qui est pratique courante/bonne pratique). Mais pour répondre à votre question, FILTER_SANITIZE_EMAIL
n'est pas inutile. C'est un filtre qui nettoie les e-mails et il fait bien son travail.
Vous avez besoin de comprendre qu'un filtre valide renvoie true
ou false
alors qu'un filtre assainit modifie en fait la variable donnée. Les deux ne servir le même but.
j'ai lu le même article et j'ai pensé la même chose: changer simplement une variable invalide n'est pas suffisant. Nous avons besoin de dire à l'utilisateur qu'il y avait un problème, au lieu de simplement l'ignorer. La solution, je pense, est de comparer l'original à la version aseptisée. C'est-à-dire: pour utiliser l'exemple w3schools, il suffit d'ajouter:
$cleanfield=filter_var($field, FILTER_SANITIZE_EMAIL);
if($cleanfield != $field){
return FALSE;
}
Ne pas réinventer la roue, laissez votre serveur de messagerie de faire le travail:la vérification/validation des courriels est une question trop complexe pour tout faire à la main. Par exemple: les courriels valides peuvent, en fait, contenir des espaces selon la RFC2822. Sans même mentionner IDN.
Échapper à tous de sortie pour être sûr de XSS. Échapper paramètres SQL comme d'habitude. Utilisez des requêtes préparées. Si vous échappez correctement toutes vos entrées et sorties, alors ce que vous enregistrez dans une base de données n'a pas d'importance, donc assainir ce type de données est inutile.
résultat:
- vérifier les e-mails seulement pour l'exactitude de base,
- utiliser
FILTER_VALIDATE_EMAIL
si vous avez d', - ne pas utiliser
FILTER_SANITIZE_EMAIL
pour l'utilisateur des données soumises.
(la Pensée, on peut noter que sur certaines anciennes versions de PHP FILTER_VALIDATE_EMAIL
n'a pas fait son travail bien pour un site internet typique: il va vous dire que john@gmail
est un email valide.)