Validation automatique des données avec HTML5 et Spring3
J’ai appris il y a longtemps qu’il était toujours nécessaire de contrôler et valider les données saisies par vos utilisateurs, du côté client comme du côté serveur (en HTML/JavaScript et en Java pour ma part), car généralement les erreurs ou les attaques viennent de là. Je n’ai jamais apprécié personnellement cette partie du travail car c’est à chaque fois la même chose et à chaque fois on doit tout refaire à la main …

Validation côté client (HTML5)
Avec HTML5 la validation de surface se fait déjà plus aisément, les nombreux « type » paramétrable dans nos champs de saisie limitent considérablement la saisie au mauvais format, exemple : , , , … (liste complète ici avec support des différents navigateurs).
Ensuite de nouveaux attributs ont vu le jour comme required, min, max, list … qui nous évitent de devoir contrôler que le champ est bien saisi, qu’il est compris dans un intervalle donné ou bien qu’il fait partie d’une liste prédéfinie de valeurs.
Dans mon nouveau projet j’utilise HTML5 comme validateur client de surface plutôt que JavaScript.
Les données envoyées au serveur sont au format JSON, la transformation de mon formulaire en objet JSON est faite avec form2js et l’envoi se fait avec jQuery de la façon suivante :
$("form").submit(function(event) {
var action = $(this).attr('action');
var formAsObject = $(this).toObject(); // form2js
$.ajax({
url: action,
type: "post",
data: formAsObject,
dataType: 'json',
success: function(jsonFromServer) {
// callback du serveur
}
});
return false;
});A retenir : il faut utiliser la méthode « submit » de jQuery sur le formulaire plutôt que la méthode « on » ou « bind » sur le bouton submit car sinon la validation des données en HTML5 ne se fera pas.
Validation côté serveur (Spring3)
C’est là que Spring3 entre en jeu ainsi que ses nombreuses annotations qui nous facilitent la tâche, dans notre cas je parle de @ModelAttribute et @Validated.
@RequestMapping(value="/login", method=RequestMethod.POST)
@ResponseBody
public UserModel login(@Validated({ UserLoginGroup.class }) @ModelAttribute UserModel user, BindingResult result, HttpServletRequest request, HttpServletResponse response) {
// validation de surface faite avec @annotations
if (result.hasErrors()) {
// des erreurs de validation
} else {
// aucune erreur de validation en surface
}
}La première (@ModelAttribute) permet de transformer automatiquement l’objet json envoyé par notre requête Ajax en objet Java : chaque attribut de l’objet json ayant le même nom (case sensitive) qu’un attribut de l’objet Java sera récupéré automatiquement.
La seconde (@Validated) indique que l’objet annoté doit être validé, la validation est écrite uniquement via des annotations, il en va de même pour les messages d’erreur à retourner. J’utilise les annotations de Hibernate Validator qui offrent un plus grand choix, allant de @Email à @NotBlank en passant par @Future pour valider que la date saisie est dans le futur.
Malheureusement il n’existe encore aucun moyen nativement de comparer deux attributs de l’objet à valider, par exemple « email » et « emailConfirm » ou encore « password » et « passwordConfirm », la communauté s’en est chargé en créant une annotation maison « FieldMatch » que j’utilise et qui marche à merveille, voici le lien vers cette annotation.
Vous l’avez compris, avec Spring3 la validation côté serveur est rendue très simple, voici un copier coller d’un objet que je valide automatiquement avec cette méthode :
@FieldMatch.List({
@FieldMatch(first = "password", second = "passwordConfirm", message = "Votre confirmation de mot de passe est invalide", groups = { UserRegisterGroup.class }),
@FieldMatch(first = "email", second = "emailConfirm", message = "Votre confirmation d'email est invalide", groups = { UserRegisterGroup.class })
})
public class UserModel implements Serializable {
private static final long serialVersionUID = -6014837207296264624L;
@NotBlank(message = "Votre email est obligatoire", groups = { UserLoginGroup.class, UserRegisterGroup.class, UserLostPasswordGroup.class })
@Email(message = "Votre email a un format incorrect", groups = { UserLoginGroup.class, UserRegisterGroup.class, UserLostPasswordGroup.class })
@Length(min=3, max=100, message = "Votre email doit faire entre 3 et 100 caractères", groups = { UserLoginGroup.class, UserRegisterGroup.class, UserLostPasswordGroup.class })
private String email;
// FieldMatch suffit pour les contrôles
private String emailConfirm;
@NotBlank(message = "Votre mot de passe est obligatoire", groups = { UserLoginGroup.class, UserRegisterGroup.class })
@Length(min=6, max=100, message = "Votre mot de passe doit faire entre 6 et 100 caractères", groups = { UserLoginGroup.class, UserRegisterGroup.class })
private String password;
// FieldMatch suffit pour les contrôles
private String passwordConfirm;
Suite de l'article :
Après :
10h47
10h46
10h46
10h28
8h05
7h58
0h15
9 mai 2012
20h51
19h18
17h00
14h48
11h54
11h32
11h14
8h38
4h58
0h00
8 mai 2012
22h40
17h03
11h23
9h12
7h23
7 mai 2012
19h14
17h37
17h09
16h31
15h37
15h05
12h29
10h45
2h05
0h17
6 mai 2012
22h24
16h56
11h33
11h20
3h00
2h15
5 mai 2012
20h05
19h20
15h09
14h06
0h00
4 mai 2012
22h05
18h51
17h35
16h25
15h59
14h55
12h58
12h46
11h44
10h45
9h28
6h59
3 mai 2012
22h26
19h18
18h05
17h34
16h44
14h28
12h57
11h29
10h22
9h00
0h00
2 mai 2012
19h47
17h25
16h01
14h07
11h36
10h22
10h10
9h09
5h01
3h49
3h29
1 mai 2012
19h37
9h42
6h58
4h59
0h31
30 avril 2012
19h40
13h06
10h47
10h34
29 avril 2012
16h11
15h58
11h56
10h50
3h00
28 avril 2012
23h53
27 avril 2012
21h54
17h24
16h18
13h13
12h06
10h28
9h17
6h57
3h56
26 avril 2012
19h10
18h23
17h57
17h03
16h45
16h00
15h06
14h45
13h36
12h37
12h30
11h24
9h12
25 avril 2012
20h17
19h51
17h56
16h21
14h51
10h26
8h58
2h10
24 avril 2012
19h00
18h54
15h58
15h44
15h28
15h25
15h22
14h41
14h39
9h14
8h58
6h57
6h42
2h31
23 avril 2012
20h09
19h55
18h26
18h00
17h58
15h44
10h24
8h03
22 avril 2012
23h31
18h30
15h21
3h00
2h04
21 avril 2012
13h20
13h18
20 avril 2012
21h54
19h19
16h04
15h31
12h34
12h01
6h59
6h43
19 avril 2012
17h16
12h56
11h39
2h16
18 avril 2012
14h06
13h00
11h55
10h41
8h00
17 avril 2012
21h43
17h28
17h13
13h21
12h44
10h09
9h14
16 avril 2012
18h57

