Une implémentation de reCAPTCHA avec ASP.NET MVC 5 et un formulaire AJAX

Tout développeur web qui a eu à mettre en place un formulaire publiquement disponible sur un site web a été exposé à la problématique du spam de formulaires. Dans certains cas, ce n’est pas si grave que cela. Cependant, nous avons tous eu à faire le formulaire de type « Contactez-nous », « Inscrivez-vous à notre infolettre » ou même « Laissez un commentaire » qui, par leur conception, attire les soumissions indésirées comme le marchand de glace par une journée chaude de juillet.

Développeurs web, nous nous raconterions des bêtises si nous ignorions le problème. Le phénomène de spam de formulaire existe, car il n’y a pas de solutions faciles. De nos jours, la raison même d’exister de ces formulaires est de permettre au propriétaire du site d’obtenir quelque chose de son visiteur. Ce qui est dommage c’est que la proportion spam versus les soumissions de formulaire légitimes sont disproportionnées.

Alors, dans ce cas, comment se protège-t-on d’un spammeur de formulaires? La première idée est d’y aller avec la technique du pot de miel. Il existe beaucoup de variations de ce cas. Généralement, il s’agit de laisser un champ que vous n’utiliserez pas, préférablement invisible pour l’utilisateur, que le robot de spam, va remplir bêtement. Si ce champ contient une saisie, vous pouvez ignorer la requête.

Cette technique peut avoir un certain succès selon la popularité de votre formulaire. Toutefois, il ne faut jamais sous-estimer la capacité d’un robot à faire des essais d’envoi de formulaire jusqu’à ce qu’il y ait une combinaison gagnante. Je vous le dis!

Qu’est-ce qui reste ensuite? Il y a le CAPTCHA. Le CAPTCHA ajoute un coefficient de difficulté supplémentaire à la saisie du formulaire en y ajoutant une combinaison de lettres et de chiffres que vous devez lire et retranscrire. Habituellement, ces combinaisons sont générées de façon à ce qu’elles soient difficiles à analyser avec un algorithme de reconnaissance d’image.

Configurer reCAPTCHA avec ASP.NET MVC 5 et un formulaire AJAX

Pour un client, j’ai eu à mettre en place un formulaire AJAX utilisant le populaire composant reCAPTCHA. Mon choix s’est arrêté sur la librairie reCAPTCHA for .NET car elle permettait de gérer la génération du captcha dans mes vues MVC  ainsi que la validation de la saisie côté serveur.

Cependant, il y a un bémol à mettre en évidence avec cette librairie. reCAPTCHA for .NET supporte uniquement, pour le moment, les formulaires réguliers. Lorsque je fais mention de formulaires réguliers, je fais référence à ceux qui utilisent Html.BeginForm contrairement à ceux qui font usage de Ajax.BeginForm.

Si vous voulez toucher au code que j’ai utilisé pour faire ce billet, vous pouvez y accéder à l’URL suivante https://github.com/pparadis/FrenchCoding.Web.reCAPTCHA.

Page de contact

La façon de contourner cette limitation est assez simple. Il suffit de faire appel au script JavaScript permettant de créer un CAPTCHA manuellement.


@using System.Configuration
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script&gt;
<script type="text/javascript">
$(document).ready(function () {
captcha();
});
function captcha() {
Recaptcha.create("@(ConfigurationManager.AppSettings["recaptchaPublicKey"])", "captcha",
{
theme: "red", callback: Recaptcha.focus_response_field
});
}
</script>
<div id="target">
@Html.Partial("Form")
</div>

view raw

contact.cshtml

hosted with ❤ by GitHub

Vue de formulaire

L’astuce ici est de faire appel à la fonction captcha lorsque l’événement OnComplete du formulaire AJAX est généré. C’est à ce moment que nous devons recréer un formulaire reCAPTCHA.


@using (Ajax.BeginForm("Form", "Home", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "target", OnComplete = "captcha(this)"}))
{
@Html.ValidationSummary()
<div id="captcha"></div>
<input type="submit" value="Submit" />
}

view raw

form.cshtml

hosted with ❤ by GitHub

Action de contrôleur


[HttpPost]
public async Task<ActionResult> Form()
{
RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper();
if (String.IsNullOrEmpty(recaptchaHelper.Response))
{
ModelState.AddModelError("", "Le captcha ne peut être vide.");
return PartialView();
}
RecaptchaVerificationResult recaptchaResult = await recaptchaHelper.VerifyRecaptchaResponseTaskAsync();
if (recaptchaResult != RecaptchaVerificationResult.Success)
{
ModelState.AddModelError("", "Réponse captcha invalide.");
return PartialView();
}
if (ModelState.IsValid)
{
return PartialView("_FormResult");
}
return PartialView();
}

view raw

controlleur.cs

hosted with ❤ by GitHub

Si vous voulez plus de French Coding, n’hésitez pas à suivre la page Facebook ou de me suivre sur Twitter.