martes, 22 de diciembre de 2015

Validar Formularios en Spring MVC

Uno de los temas más importantes en cuanto a la seguridad y la prevención de errores es la validación de los datos de entrada de los usuarios en el servidor. No podemos limitarnos a realizar validaciones únicamente en el cliente, ya que de forma muy fácil se pueden saltar estos mecanismos, y la
Spring Logo
validación por ejemplo mediante javascript en el navegador se utiliza para mejorar la experiencia del usuario, pero nunca debe ser un sustituto de la validación en el servidor.

No es necesario validar los datos en los métodos del controlador, desde la versión 3 de Spring Framework, tenemos compatibilidad con la API de validación de Java (JSR-303) y no es necesaria ninguna configuración adicional, basta con incluir una implementación de la API como Hibernate Validator en las librerías del proyecto:




Si usas maven es tan simple como:

<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.2.Final</version>
</dependency>

En quieres añadir la librería directamente debes descargar e incluir en tu proyecto la librería hibernate-validator-5.2.2.Final.jar (versión estable más reciente al escribir este artículo) de http://hibernate.org/validator/downloads/

En este ejemplo vamos a validar las variables de nuestra clase User del ejemplo anterior, mediante anotaciones:

El campo id vamos a especificar un valor mínimo de 1 y máximo de 10:

@Min(1)
@Max(10)
 private int id;

La alternativa mediante Hibernate Validator es con la anotacion @Range(min=1,max=10)

Para los String vamos a definir también un número mínimo y máximo de caracteres:
@Size(min=4, max=10)
 private String name;
@Size(min=6)
 private String password;

Para evitar valores en blanco utilizamos la anotación @NotNull
@NotNull
 private String country;


Para fechas tenemos las anotaciones @Past y @Future, que obligan a introducir una fecha pasada y futura respectivamente, pero utilizando la clase Date. Con la nueva API para fechas de Java 8 y en nuestro ejemplo anterior utilizamos LocalDate, sería necesario implementar nuestro propio validador y eso lo dejaré para un próximo artículo.

Para el correo electrónico podríamos usar la anotación @email, pero si queremos ser más restrictivos podríamos usar una expresión regular, aplicable a Strings como una password si queremos que por ejemplo contenga una mayúscula mas un carácter especial etc, la forma de utilizar una expresión regular sería la siguiente:

@Pattern(regexp = "^[\w-_\.+]*[\w-_\.]\ @([\w]+\.)+[\w]+[\w]$")
 private String Email;


La lista de anotaciones disponibles la podéis encontrar en:
https://docs.oracle.com/javaee/7/tutorial/bean-validation001.htm
y la lista adicional de hibernate validator en la siguiente tabla:
http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html_single/#table-custom-constraints

Nuestro clase User quedaría:


public class User {
    //@Min(1)
    //@Max(10)
    @Range(min=1,max=10)
    private int id;    
    @Size(min=4, max=10)
    private String name;
    @Size(min=6)
    private String password;
    
    //@Email    
    @Pattern(regexp = "^[\\w-_\\.+]*[\\w-_\\.]\\ @([\\w]+\\.)+[\\w]+[\\w]$")        
    private String email;
    @NotNull
    @DateTimeFormat(pattern="dd/MM/yyyy")    
    private LocalDate birthDate;    
    @NotNull
    private String country;

    public User() {
    }   
//getters and setters
}

Modificando nuestro formulario:
Ahora es necesario incluir la etiqueta "errors", para mostrar un mensaje al usuario en el caso de que el formulario no sea correcto.


<form:label path="id">Id</form:label>
<form:input path="id" cssErrorClass="formError"/>
<form:errors path="id"/>          

<form:label path="name">Name</form:label>
<form:input path="name" cssErrorClass="formError"/>
<form:errors path="name"/>

...

En el controlador tenemos que realizar una pequeña modificación en el caso de que los datos enviados por el usuario sean inconsistentes que los complete de nuevo:

@RequestMapping(value = "result", method = RequestMethod.POST)
    public String Form(@Valid User user, Errors errors, Model model) {
        if(errors.hasErrors()) {
            model.addAttribute("countries",countries);
            model.addAttribute("user", user);
            return "home";
        }
        model.addAttribute("user", user);
        return "user";
    } 

La anotación @Valid es la que determina que user sea validado, es importante que el parámetro que se le pase a continuación de user sea errors, sino puede dar errores 400, aunque se podría sustituir Error errors por BindingResult result y utilizar result.hasErrors().

El resultado del formulario sería:



El código completo del ejemplo lo puedes encontrar en mi repositorio de Github:
https://github.com/Jaime-Alonso/TutorialSpringMVC


No hay comentarios:

Publicar un comentario