2011-02-08 11 views
6

Estoy usando JSR303 y creé una restricción de nivel de clase que compara la contraseña y su confirmación en un formulario, que Voy a nombrar aquí la restricción @SameAs. Idealmente, me hubiera gustado asociar la restricción con el objetivo deseado (confirmPassword), pero obviamente el bean adjunto no está disponible para extraer la contraseña. - de ahí la restricción de nivel de clase.JSR303: Intentar personalizar una violación de restricción para asociarla con una subruta en un validador de restricción de relación de nivel de clase

He leído con interés otras publicaciones que demuestran cómo aprovechar las restricciones de nivel de clase para validar relaciones, pero no encuentro nada que explique cómo la violación de restricciones puede personalizarse para asociarse con una subruta, en este caso de los dos campos en la relación.

Mi pregunta es la siguiente: ¿cómo asociaría el mensaje de la violación de restricción con el campo 'confirmPassword' en lugar del objeto de nivel superior? He intentado usar el parámetro de contexto de javax.Validator.validate (destino, contexto), pero agregar un nodo dentro del validador para @SameAs causa una excepción para la siguiente restricción en la cascada (tratando de extraer la propiedad confirmPassword -> orderNumber en lugar de ordenar -> orderNumber) como resultado.

Por el momento he recurrido a un feo kludge al crear una propiedad adicional que almacena el mensaje de restricción que se extrae para su uso cerca del campo de entrada confirmPassword en la capa web.

Seguramente me estoy perdiendo algo aquí .... por favor, véase el siguiente ejemplo

Gracias por cualquier comentario

Ejemplo

@Constraint(validatedBy = { SamePwdAsValidator.class}) 
public interface SamePwdAs {//... 
} 

//Using passwords in an order doesn't make sense - only for demo purpose 
@SamePwdAs(message = "Password and confirmation must match" ...) 
public class Order { 

    @NotNull 
    @Size(....) 
    String pwd; 

    //where I would really like to use @SameAs, and associate a violation 
    String pwdConfirm; 

    @NotNull (...) 
    @Pattern (....) 
    String orderNumber; 

    //...getters/setters 
} 

public class SamePwdAsValidator implements javax.validation.Validator { 
//... 
    public boolean isValid(Object target, ValidationContext ctx) { 
    String tgt = target.getPwd(), other = target.getPwdConfirm() 
    boolean isValid = tgt.equals(other); 

    if (!isValid) { 
     //try to configure the context subpath for pwdConfirm to associate this constraint violation with: I tried 
     //ctx.addNode('pwdConfirm').addConstraintViolation() which doesn't work, as the next validator will 
     //bump into trying to extract Order.pwdConfirm.orderNumber and throw a NoPropertyFoundException or the like 
    } 

    return isValid; 
} 

Respuesta

5

que voy a dar 2 respuestas.

Respuesta 1, que trata de responder a su pregunta:

utilizo un método de utilidad este modo:

public static final void recreateConstraintViolation(ConstraintValidatorContext constraintValidatorContext, String errorCode, String fieldName) { 
     constraintValidatorContext.disableDefaultConstraintViolation(); 
     constraintValidatorContext.buildConstraintViolationWithTemplate(errorCode). 
     addNode(fieldName).addConstraintViolation(); 

} 

Y luego, en su validador donde se comparan las dos contraseñas:

if (!isValid) { 
    for (String fieldName : fieldNames) { 
     CustomConstraintUtils.recreateConstraintViolation(constraintValidatorContext, "password.password2.mismatch", fieldName); 
    } 
    return false; 
} 

Respuesta 2

Le sugiero que utilice un marco de seguridad como Spring Security para cuidar la coincidencia de contraseñas, ya que supongo que su caso de uso se trata de un inicio de sesión de usuario.

Cuestiones relacionadas