Валидатор Hibernate: @Email принимает ask @ stackoverflow как действительный? - PullRequest
47 голосов
/ 16 декабря 2010

Я использую аннотацию @Email для подтверждения адреса электронной почты. У меня проблема в том, что он принимает такие вещи, как ask@stackoverflow, как действительный адрес электронной почты. Я думаю, это потому, что они хотят поддерживать адреса в интрасети, но я не могу найти флаг, поэтому он проверяет расширение.

Мне действительно нужно переключиться на @Pattern (и любые рекомендации для гибкого шаблона электронной почты) или я что-то упустил?

Ответы [ 8 ]

49 голосов
/ 20 сентября 2012

Вы также можете использовать состав ограничения в качестве обходного пути.В приведенном ниже примере я использую валидатор @Email для выполнения основной валидации и добавляю валидатор @Pattern, чтобы убедиться, что адрес имеет форму x@y.z (я не рекомендую использовать только @Pattern ниже для обычной проверки электронной почты)

@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 {};
}
33 голосов
/ 16 декабря 2010

На самом деле, @Email из Hibernate Validator использует регулярное выражение внутренне . Вы можете легко определить собственное ограничение на основе этого регулярного выражения, измененного по мере необходимости (обратите внимание на + в конце 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
                    + ")$";
}
15 голосов
/ 13 октября 2014

На самом деле проверка адресов электронной почты действительно сложна.Невозможно проверить, что адрес электронной почты является синтаксически правильным и адресован предполагаемому получателю в аннотации.@Email аннотация является полезной минимальной проверкой, которая не страдает от проблемы ложных негативов.

Следующим этапом проверки должна быть отправка электронного письма с запросом, который пользователь должен выполнить.убедитесь, что у пользователя есть доступ к адресу электронной почты.

Лучше принять несколько ложных срабатываний на шаге 1 и разрешить пропуск некоторых недействительных адресов электронной почты, чем отклонять действительных пользователей.Если вы хотите применить дополнительные правила, вы можете добавить больше проверок, но будьте очень осторожны с тем, что вы считаете обязательным требованием действительного адреса электронной почты.Например, в RFC нет ничего, что предписывало бы, что i@nl будет недействительным, поскольку nl является зарегистрированным доменом верхнего уровня страны.

3 голосов
/ 05 сентября 2015

Вот валидатор электронной почты javax.validation с использованием 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);
    }
}

И аннотация:

@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();
    }
}
0 голосов
/ 20 ноября 2018

Вы можете использовать регулярное выражение электронной почты, также убедившись, что проверка не завершится неудачно, если электронная почта пуста.

@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 {};
}
0 голосов
/ 18 июля 2018

Если вы собираетесь попробовать вышеуказанное решение https://stackoverflow.com/a/12515543/258544, добавьте @ReportAsSingleViolation в определение аннотации, таким образом вы избежите как сообщения проверки (одно из @Email, так и одно из @Pattern), поскольку составленная аннотация:

@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

Из @interface ReportAsSingleViolation javax.validation: validation-api: 1.1.0.Final) определение аннотации: «... Оценка составленных ограничений останавливается на первой проверке ошибка в том случае, если налагаемое ограничение снабжено пометкой ReportAsSingleViolation "

0 голосов
/ 03 июля 2017

Очевидно, я опаздываю на вечеринку, но я отвечаю на этот вопрос,

Почему мы не можем использовать аннотацию @Pattern с регулярными выражениями в нашем классе валидации, например,

public Class Sigunup {

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

}

Это легче.

0 голосов
/ 25 августа 2014

Решение с ограничением композиции не работает. Когда электронная почта используется вместе с шаблоном, регулярное выражение электронной почты имеет более высокий приоритет. Я полагаю, что это потому, что аннотация электронной почты переопределяет некоторые атрибуты Pattern, а именно флаги и регулярное выражение (здесь ключ). Если я удаляю @Email, только тогда регулярное выражение @Pattern будет применяться в проверках.

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