Hibernate验证器:@Email接受询问 @stackoverflow是有效的吗?
-
10-10-2019 - |
题
我正在使用 @Email
注释以验证电子邮件地址。我遇到的问题是它正在接受类似的东西 ask@stackoverflow
作为有效的电子邮件地址。我想这是因为他们想支持Intranet地址,但是我似乎找不到标志,因此它确实检查了扩展名。
我真的需要切换 @Pattern
(以及关于灵活的电子邮件模式的任何建议)还是我错过了什么?
解决方案
实际上, @Email
来自Hibernate验证器 内部使用REGEXP. 。您可以根据需要修改的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
是注册国家的顶级领域。
这是使用Apache Commons验证器的Javax.Validation电子邮件验证器
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 { };
您可以使用电子邮件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:验证-API:1.1.0.-final)注释定义:“ ...对组成约束的评估在第一个验证错误上停止,以防构成约束用reportassingleviolation注释“