webentwicklung-frage-antwort-db.com.de

Hibernate-Validator: @Email akzeptiert ask @ stackoverflow als gültig?

Ich verwende die Annotation @Email, um eine E-Mail-Adresse zu überprüfen. Das Problem, das ich habe, ist, dass [email protected] als gültige E-Mail-Adresse akzeptiert wird Ich unterstütze Intranet-Adressen, aber ich finde anscheinend kein Flag, also wird nach einer Erweiterung gesucht.

Muss ich wirklich zu @Pattern (und den Empfehlungen für ein E-Mail-Muster, das flexibel ist) wechseln, oder fehlt mir etwas?

47
jack

Tatsächlich verwendet @Email von Hibernate Validator regexp intern . Sie können einfach Ihre eigene Einschränkung basierend auf diesem regulären Ausdruck definieren, der nach Bedarf geändert wird (beachten Sie den + am Ende von 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
                    + ")$";
}
33
axtavt

Sie können auch constraint composition als Problemumgehung verwenden. In dem folgenden Beispiel verlasse ich mich auf den @Email Validator, um die Hauptvalidierung durchzuführen, und füge einen @Pattern Validator hinzu, um sicherzustellen, dass die Adresse in der Form [email protected] ist (nicht wahr) Verwenden Sie zur regelmäßigen E-Mail-Überprüfung nur den unten stehenden Code @Pattern

@Email(message="Please provide a valid email address")
@Pattern(regexp="[email protected]+\\..+", 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 {};
}
46
Matt

Das Überprüfen der E-Mail-Adressen ist sehr komplex. Es kann nicht überprüft werden, ob eine E-Mail-Adresse syntaktisch korrekt ist und den beabsichtigten Empfänger in einer Anmerkung anspricht. Die @Email-Annotation ist eine nützliche Minimalprüfung, die nicht unter dem Problem falscher Negative leidet.

Der nächste Schritt der Validierung sollte das Senden einer E-Mail mit einer Herausforderung sein, die der Benutzer ausführen muss, um festzustellen, ob der Benutzer Zugriff auf die E-Mail-Adresse hat.

Es ist besser, in Schritt 1 einige Fehlalarme zu akzeptieren und zulassen, dass einige ungültige E-Mail-Adressen weitergeleitet werden, anstatt gültige Benutzer abzulehnen. Wenn Sie zusätzliche Regeln anwenden möchten, können Sie weitere Überprüfungen hinzufügen. Achten Sie jedoch darauf, dass Sie eine gültige E-Mail-Adresse als Voraussetzung betrachten. Beispielsweise gibt es in den RFCs nichts, was besagt, dass [email protected] ungültig sein würde, da nl eine registrierte oberste Domäne eines Landes ist.

14
David

Hier ist ein javax.validation-E-Mail-Validator, der den Apache Commons-Validator verwendet

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);
    }
}

Und die Anmerkung:

@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();
    }
}
3
Neil McGuigan

Die Constraint Composition-Lösung funktioniert nicht. Wenn E-Mail in Verbindung mit Muster verwendet wird, hat der Regex für E-Mails eine höhere Priorität. Ich glaube, das liegt daran, dass die Email-Annotation einige Musterattribute überschreibt, nämlich flags und regexp (der Schlüssel hier). Wenn ich @Email entferne, wird nur der reguläre @Pattern-Ausdruck in Validierungen angewendet. 

/**
 * @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 { };
0
user1048931

Offensichtlich komme ich zu spät zur Partei. Trotzdem beantworte ich diese Frage. 

Warum können wir @Pattern-Annotation nicht mit regulären Ausdrücken in unserer Validation-Klasse verwenden? 

public Class Sigunup {

    @NotNull
    @NotEmpty
    @Pattern((regexp="[A-Za-z0-9._%-+][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
    private String email;

}

Es ist einfacher. 

0
user2245151

Wenn Sie die obige Lösung versuchen https://stackoverflow.com/a/12515543/258544 - @ReportAsSingleViolation in die Anmerkungsdefinition einfügen, vermeiden Sie auf diese Weise beide Überprüfungsnachrichten (eine von @Email und eine von @Pattern), da es sich um eine zusammengesetzte Anmerkung handelt: 

@Email(message="Please provide a valid email address")
@Pattern(regexp="[email protected]+\\..+", message="Please provide a valid email address")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
@ReportAsSingleViolation

Aus @schnittstelle ReportAsSingleViolation javax.validation: validation-api: 1.1.0.Final) Anmerkungsdefinition: "... Die Bewertung zusammengesetzter Integritätsbedingungen stoppt beim ersten Validierungsfehler Wenn die zusammengesetzte Integritätsbedingung mit ReportAsSingleViolation kommentiert wird "

0

Sie können Email Regex verwenden, um sicherzustellen, dass die Überprüfung nicht fehlschlägt, wenn die E-Mail leer ist.

@Email(regexp = "[email protected]+\\..+|")
@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 {};
}
0
Davithbul