J'utilise l'annotation @Email
pour valider une adresse électronique .Le problème que je rencontre est qu'il accepte des éléments tels que ask@stackoverflow
comme adresse électronique valide . Je suppose que c'est parce qu'ils veulent supporte les adresses intranet, mais je n'arrive pas à trouver un drapeau, donc il vérifie la présence d'une extension.
Dois-je vraiment passer à @Pattern
(et des recommandations pour un modèle de courrier électronique flexible) ou ai-je oublié quelque chose?
En fait, @Email
de Hibernate Validator utilise regexp en interne . Vous pouvez facilement définir votre propre contrainte basée sur cette expression rationnelle, modifiée selon vos besoins (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
+ ")$";
}
Vous pouvez également utiliser composition de contraintes comme solution de contournement. Dans l'exemple ci-dessous, je m'appuie sur le validateur @Email
pour effectuer la validation principale et ajouter un validateur @Pattern
pour m'assurer que l'adresse est sous la forme [email protected]
(je ne recommande pas d'utiliser uniquement le @Pattern
ci-dessous pour la validation régulière par courrier électronique).
@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 réalité, la validation des adresses e-mail est vraiment complexe. Il n'est pas possible de valider qu'une adresse électronique est syntaxiquement correcte et adresse le destinataire voulu dans une annotation. L'annotation @Email
est une vérification minimale utile qui ne souffre pas du problème des faux négatifs.
La prochaine étape de la validation devrait consister à envoyer un courrier électronique avec un défi que l’utilisateur doit terminer pour établir qu’il a accès à l’adresse électronique.
Il est préférable d’accepter quelques faux positifs à l’étape 1 et de laisser passer des adresses électroniques non valides plutôt que de rejeter des utilisateurs valides. Si vous souhaitez appliquer des règles supplémentaires, vous pouvez ajouter davantage de contrôles, mais faites très attention à ce que vous supposez être une adresse de messagerie valide. Par exemple, rien dans les RFC n'indique que i@nl
serait invalide, car nl
est un domaine de premier niveau enregistré.
Voici un validateur de courrier électronique 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();
}
}
La solution de composition de contrainte ne fonctionne pas. Lorsque Email est utilisé avec Pattern, la regex Email est conservée avec une priorité supérieure. Je pense que cela est dû au fait que l'annotation Email remplace quelques attributs de modèle, à savoir flags et regexp (la clé ici). Si je supprime @Email
, l'expression régulière @Pattern
s'appliquera uniquement lors des 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 { };
Évidemment, je suis en retard au Parti, je réponds néanmoins à cette question,
Pourquoi ne pouvons-nous pas utiliser l'annotation @Pattern avec des expressions régulières dans notre classe de validation comme celle-ci
public Class Sigunup {
@NotNull
@NotEmpty
@Pattern((regexp="[A-Za-z0-9._%-+]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
private String email;
}
C'est plus facile.
Si vous essayez la solution ci-dessus https://stackoverflow.com/a/12515543/258544 ajoutez le @ReportAsSingleViolation dans la définition de l'annotation, vous éviterez ainsi le message de validation (un de @Email et un de @Pattern) car il s’agit d’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 s'arrête à la première validation Erreur au cas où la contrainte de composition est annotée avec ReportAsSingleViolation "
Vous pouvez utiliser Email regexp, en vous assurant également que la validation n'échoue pas lorsque l'email 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 {};
}