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>
<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.

Publicité

Les liens de la semaine – Édition #103

Développement

.NET

ASP.NET vNext

Technologie

Web

  • Votre vie sur terre. Un exercice de visualisation intéressant sur les événements survenus durant votre vie de la part de la BBC.

Science et autres

Pour une redirection temporaire, faut-il utiliser le code HTTP 302 ou 307?

Il semble que, depuis que le web est ce qu’il est, la façon officielle de faire une redirection temporaire est d’envoyer au navigateur web le code HTTP 302. Un collègue m’est arrivé avec cette remarque l’autre jour. Pourquoi utiliser le code HTTP 302 pour faire une redirection temporaire alors que le code 307 Temporary Redirect existe?

Une mise en contexte s’impose

La première, la plus connue, est la redirection 301. Cette redirection, permanente, permet d’indiquer que la ressource demandée sera dorénavant accessible à une nouvelle adresse. La deuxième est la 302. Cette redirection est un utilitaire lorsqu’il est temps de déplacer un visiteur sur une autre page sans affecter l’indexation d’une page.

Cette affirmation est vraie. En particulier pour le monde du SEO où ces deux codes HTTP font foi de tout lorsqu’il est temps d’indexer une page web.

Alors donc, pourquoi parlons-nous encore du code HTTP 302 pour les redirections temporaires alors qu’il existe un code ayant une définition plus claire et pertinente? La raison est simple. Le code HTTP 307 appartient à la révision 1.1 du protocole HTTP. Cela veut dire qu’aux débuts d’internet, il y avait uniquement le code 302 et c’est ainsi que nous avons pris l’habitude de l’utiliser.

Comme HTTP/1.1 est un ajout à la version 1.0 de la spécification du protocole, les deux codes cohabitent parfaitement. D’autant plus que, le protocole HTTP étant ce qu’il est, il revient au client web de spécifier quelle version du protocole HTTP il préfère communiquer avec le serveur. Certains clients HTTP vont indiquer une préférence pour HTTP/1.0, malgré ses limitations, afin de bénéficier de la souplesse du protocole sur le nombre de connexions simultanées à un serveur.

Comment faire une redirection 307 avec ASP.NET MVC 5

Alors donc, si la rétrocompatibilité absolue envers les clients HTTP n’est pas votre genre, sachez qu’il est possible de faire une redirection HTTP 307 avec ASP.NET MVC sans problèmes.

De plus, considérez ceci. Les chances que vous aillez à supporter un client exigeant uniquement HTTP/1.0 sont assez minces. En particulier si vous faites du développement web comme moi. Pensez-y. Les sites que j’ai récemment développés sont uniquement compatibles avec Internet Explorer 9 et plus. Pas de problèmes de ce côté, n’est-ce pas?


public ActionResult About()
{
HttpContext.Response.AddHeader("Location", "/Home/Contact");
return new HttpStatusCodeResult(307);
}

view raw

redirect.cs

hosted with ❤ by GitHub

Ce code va produire les requêtes HTTP suivantes:

fiddler-307

 

Une dernière pensée à ce sujet

À cette époque-ci, il est de moins en moins nécessaire de connaitre par cœur tous les codes HTTP pour arriver à faire du développement web. Toutefois, il est vraiment important de connaitre certains essentiels. Notamment comment les codes sont regroupés.

Est-ce que vous vous demandez quel est le rapport avec les redirections HTTP? Il y en a très peu, en fait. C’est juste que j’ai trouvé le tweet assez drôle et tant qu’à être dans le sujet du protocole HTTP, je n’ai pas pu m’empêcher!

Les liens de la semaine – Édition #102

Développement

.NET

Web

Technologie

Science et autres

  • editorconfig.org a pour but de vous aider à maintenir un style de programmation consistant à travers les éditeurs et IDE.

Comment déployer une application ASP.NET avec Web Deploy 3.5

Avec le temps, j’avais développé une sorte pensée « anti-automatisation » du déploiement d’une application. J’ai fonctionné ainsi pendant un bon moment.

Or, pendant une période de ma carrière de développeur web, j’ai eu à travailler régulièrement en support applicatif et en maintien de sites en production. Le déploiement manuel d’une application m’a permis d’être en mesure d’intervenir assez rapidement sur des cas problématiques.

Cette pensée a duré jusqu’à ce que j’aille à déployer une application web dans le cloud d’Amazon (EC2). Étant donné que l’application web serait hébergée là-bas, elle ne sera pas aussi facilement accessible que celles que j’ai développées dans le passé. Applications qui sont hébergées dans l’infrastructure de serveurs de mon employeur.

Cette distance m’a incité à faire mes petites recherches côté déploiement. Comment font les gens qui hébergent leurs applications ASP.NET chez Amazon? L’une des façons les plus populaires est d’utiliser Web Deploy. Encore une fois, j’ai apparemment manqué le bateau là dessus. WebDeploy existe depuis déjà quelque temps.

Installation de Web Deploy 3.5 sur Amazon

Lorsque j’ai entamé le projet de configurer Web Deploy sur mon instance web sur Amazon, j’ai suivi les instructions de Martin Buberl à ce sujet. Il s’avère que  les instructions sont très bien détaillées. Disons que je n’ai pas envie de les répéter dans ce billet!

Cependant, ce qui est à retenir, selon mon expérience, sont les choses suivantes:

  • Si vous installez Web Deploy par le Web Platform Installer, assurez-vous de sélectionner « Web Deploy 3.5 for hosting servers » comme l’indique le guide.
  • Assurez d’avoir installé toutes les fonctionnalités reliées à ASP.NET et IIS dans les composantes Windows. Comme j’ai précédemment mentionné, Web Platform Installer va s’installer comme un module IIS.
  • Assurez-vous d’avoir débloqué le port 8172 dans votre coupe-feu. Que ce soit par les restrictions d’Amazon ou par une configuration logicielle dans votre instance Windows, c’est le premier endroit où ça risque de ne pas fonctionner.

Vous allez remarquer aussi que le guide utilise le compte utilisateur Administrator pour faire ses déploiements. À mon avis, ce n’est pas du tout une bonne idée de procéder ainsi. Ce que je recommande c’est de créer un compte utilisateur spécialement pour cette occasion. De cette façon, vous pourrez restreindre les accès de cet utilisateur et éviter d’avoir à communiquer votre mot de passe administrateur à toute l’équipe de développement.

Pour faire cela, suivez les instructions du paragraphe « Using the iis manager to configure web deploy for a non-administrator » du guide de configuration Web Deploy de Microsoft.

Utilisation à partir de Visual Studio 2013

L’utilisation de votre WebDeploy, nouvellement configuré, à partir de votre instance Visual Studio se met en place exactement comme dans le guide précédemment indiqué.

La seule consigne à retenir en ce qui concerne le déploiement avec WebDeploy c’est que tous les fichiers présents dans votre projet web Visual Studio seront déployés. Je mentionne cela en particulier pour les fichiers de configuration contenant des éléments spécifiques pour l’environnement de développement local.

Or, la façon la plus simple de contourner ceci est de les exclure de votre projet Visual Studio. De cette façon, ils sont présents sur votre disque dur et correctement versionné sans, toutefois, affecter vos déploiements. Alternativement vous pourriez configurer le Build Action à none dans les propriétés des fichiers en questions.

Toutefois, je ne suis pas un très grand partisan de cette dernière option pour des fichiers contenant des configurations importantes. Je crois qu’il est plus simple de me dire que, si le fichier n’est pas visible, c’est qu’il ne sera pas déployé.