Hibernate varidator: @email принимает ask @Stackoverflow как действительный?
-
10-10-2019 - |
Вопрос
Я использую @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) Определение аннотации: «... Оценка составленных ограничений остановок при первой ошибке проверки в случае, если ограничение сочинения аннотируется с отчетом