Mise en veille prolongée validateur: @Email accepte @ demander stackoverflow comme valide?
-
10-10-2019 - |
Question
J'utilise l'annotation @Email
pour valider une adresse e-mail.
La question que je vais avoir est qu'il est d'accepter des choses comme ask@stackoverflow
comme une adresse e-mail valide.
Je suppose que cela est parce qu'ils veulent soutenir les adresses intranet, mais je ne peux pas sembler trouver un drapeau il ne vérifie une extension.
Ai-je vraiment besoin de passer à @Pattern
(et des recommandations pour un modèle e-mail qui est flexible) ou suis-je manque quelque chose?
La solution
En fait, @Email
de Hibernate Validator uses regExp interne . Vous pouvez facilement définir votre propre contrainte en fonction de cette expression rationnelle, modifiée que vous avez besoin (notez le +
à la fin de DOMAIN
):
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Pattern(regexp = Constants.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE)
public @interface EmailWithTld {
String message() default "Wrong email";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
interface Constants {
static final String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
static final String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)+";
static final String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
static final String PATTERN =
"^" + ATOM + "+(\\." + ATOM + "+)*@"
+ DOMAIN
+ "|"
+ IP_DOMAIN
+ ")$";
}
Autres conseils
Vous pouvez également utiliser contrainte composition comme un travail autour. Dans l'exemple ci-dessous, je compte sur le validateur @Email
faire la validation principale, et ajouter un validateur @Pattern
pour vous assurer que l'adresse est sous forme de x@y.z
(je ne recommande pas d'utiliser seulement le @Pattern
ci-dessous pour la validation régulière Email)
@Email(message="Please provide a valid email address")
@Pattern(regexp=".+@.+\\..+", message="Please provide a valid email address")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmailValidator {
String message() default "Please provide a valid email address";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
En fait valider les adresses e-mail est vraiment complexe. Il est impossible de valider une adresse e-mail est à la fois syntaxiquement correcte et adresse du destinataire dans une annotation. L'annotation @Email
est un contrôle minimal utile qui ne souffre pas du problème des faux négatifs.
L'étape suivante dans la validation devrait envoyer un e-mail à un défi que l'utilisateur doit remplir pour établir que l'utilisateur a accès à l'adresse e-mail.
Il est préférable d'être accepter quelques faux positifs à l'étape 1 et permettre à des adresses e-mail non valides de passer à travers que de rejeter les utilisateurs valides. Si vous voulez appliquer des règles supplémentaires que vous pouvez ajouter d'autres contrôles, mais faire très attention à ce que vous assumez une exigence d'une adresse e-mail valide. Par exemple, il n'y a rien dans les RFCs qui dicte que i@nl
seraient invalides, parce que nl
est un domaine de premier niveau national enregistré.
Voici un validateur email javax.validation utilisant Apache Commons Validator
public class CommonsEmailValidator implements ConstraintValidator<Email, String> {
private static final boolean ALLOW_LOCAL = false;
private EmailValidator realValidator = EmailValidator.getInstance(ALLOW_LOCAL);
@Override
public void initialize(Email email) {
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if( s == null ) return true;
return realValidator.isValid(s);
}
}
Et l'annotation:
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CommonsEmailValidator.class})
@Documented
@ReportAsSingleViolation
public @interface Email {
String message() default "{org.hibernate.validator.constraints.Email.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
Email[] value();
}
}
Il est évident que je suis en retard au Parti, encore je réponds à cette question,
Pourquoi ne puis nous utilisons l'annotation @Pattern avec des expressions régulières dans notre classe de validation comme celui-ci
public Class Sigunup {
@NotNull
@NotEmpty
@Pattern((regexp="[A-Za-z0-9._%-+]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
private String email;
}
Il est plus facile.
La solution de composition de contrainte ne fonctionne pas. Lorsque Email est utilisé en conjonction avec le modèle, l'e-mail regex est maintenu en priorité plus élevée. Je crois que c'est parce que l'annotation Email remplace quelques attributs de modèle, à savoir des drapeaux et des expressions rationnelles (celle clé ici) Si je supprime @Email
, alors seulement l'expression régulière de @Pattern
appliquer les validations.
/**
* @return an additional regular expression the annotated string must match. The default is any string ('.*')
*/
@OverridesAttribute(constraint = Pattern.class, name = "regexp") String regexp() default ".*";
/**
* @return used in combination with {@link #regexp()} in order to specify a regular expression option
*/
@OverridesAttribute(constraint = Pattern.class, name = "flags") Pattern.Flag[] flags() default { };
Vous pouvez utiliser le courrier électronique regexp, ce qui assure également que la validation ne manque pas quand l'e-mail est vide.
@Email(regexp = ".+@.+\\..+|")
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmail {
@OverridesAttribute(constraint = Email.class, name = "message")
String message() default "{javax.validation.constraints.Email.message}";
@OverridesAttribute(constraint = Email.class, name = "groups")
Class<?>[] groups() default {};
@OverridesAttribute(constraint = Email.class, name = "payload")
Class<? extends Payload>[] payload() default {};
}
Si vous allez essayer la solution ci-dessus https://stackoverflow.com/a/12515543/258544 add le @ReportAsSingleViolation
dans le defination d'annotation, de cette façon, vous éviterez à la fois un message de validation (un de @Email
et un de @Pattern
) car il est une annotation composée:
@Email(message="Please provide a valid email address")
@Pattern(regexp=".+@.+\\..+", message="Please provide a valid email address")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
@ReportAsSingleViolation
De @interface ReportAsSingleViolation
javax.validation: validation api: 1.1.0.Final) définition d'annotation:
» ... L'évaluation des contraintes composées arrête sur la première validation
erreur dans le cas où la contrainte est la composition avec annotées ReportAsSingleViolation "