Hibernate varidator: @email принимает ask @Stackoverflow как действительный?

StackOverflow https://stackoverflow.com/questions/4459474

Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

Вы также можете использовать состав ограничения как обходной. В примере ниже я полагаюсь на @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 {};
}

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

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

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

Вот валидатор электронной почты Javax.validation с использованием валидатора Apache Commons

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

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

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

public Class Sigunup {

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

}

Это легче.

Решение композиции ограничения не работает. Когда электронная почта используется в сочетании с шаблоном, регулярность электронной почты удерживается в более высоком приоритете. Я полагаю, что это потому, что аннотация электронной почты переворачивает несколько атрибутов шаблона, а именно флаги и regexp (ключевой здесь), если я удалю @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 { };

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

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

Если вы собираетесь попробовать приведенное выше решение 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) Определение аннотации: «... Оценка составленных ограничений остановок при первой ошибке проверки в случае, если ограничение сочинения аннотируется с отчетом

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top