web-dev-qa-db-ja.com

Hibernateバリデーター:@Emailはask @ stackoverflowを有効として受け入れますか?

@Email注釈を使用して、電子メールアドレスを検証しています。私が抱えている問題は、ask@stackoverflowのようなものを有効な電子メールアドレスとして受け入れることです。これは、彼らがイントラネットアドレスをサポートしたいからだと思いますが、拡張機能をチェックするためにフラグを見つけることができないようです。

本当に@Pattern(および柔軟な電子メールパターンに関する推奨事項)に切り替える必要がありますか、それとも何か不足していますか?

47
jack

実際、@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
                    + ")$";
}
33
axtavt

回避策として 制約構成 を使用することもできます。以下の例では、@Emailバリデーターを使用してメインの検証を行い、@Patternバリデーターを追加して、アドレスが[email protected]の形式であることを確認します(しない通常のメールの検証には、以下の@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 {};
}
50
Matt

実際に電子メールアドレスを検証することは本当に複雑です。電子メールアドレスが構文的に正しいことと、注釈内の目的の受信者のアドレスであることを検証することはできません。 @Email注釈は、偽陰性の問題に悩まされることのない便利な最小限のチェックです。

検証の次の手順は、ユーザーが電子メールアドレスにアクセスできることを確認するために完了する必要があるチャレンジを含む電子メールを送信することです。

有効なユーザーを拒否するよりも、手順1でいくつかの誤検出を受け入れて、無効な電子メールアドレスをパススルーすることをお勧めします。追加のルールを適用する場合は、さらにチェックを追加できますが、有効な電子メールアドレスの要件であると想定していることに十分注意してください。たとえば、nlは登録された国のトップレベルドメインであるため、i@nlが無効になることを指示するRFCには何もありません。

16
David

Apache Commons Validatorを使用した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();
    }
}
3
Neil McGuigan

明らかに私は党に遅れている、それでも私はこの質問に答えている、

このようなValidationクラスの正規表現で@Patternアノテーションを使用できないのはなぜですか

public Class Sigunup {

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

}

その簡単。

1
user2245151

上記の解決策を試してみる場合 https://stackoverflow.com/a/12515543/258544 アノテーション定義に@ReportAsSingleViolationを追加すると、この方法で両方の検証メッセージ(@電子メールと@Patternからの1つ)は、合成された注釈です。

@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

メールの正規表現を使用して、メールが空のときに検証が失敗しないようにすることもできます。

@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
Davithbul