Comment créer un Captcha maison évolutif sous Symfony
Ou comment épargner à vos utilisateurs de devoir cliquer sur des voitures.
Sécurisez sans importuner
Les systèmes de Captcha sont largement utilisés sur internet afin que nous, humains, prouvions que nous ne sommes pas des robots. Comprendre : des programmes conçus pour réaliser des actions malveillantes. Un tel programme pourrait par exemple tenter de s’inscrire en masse sur des sites internet afin de pouvoir poster des messages publicitaires de façon automatisée.
Ce dispositif de sécurité s’avère donc utile, mais souffre de plusieurs inconvénients :
- Beaucoup de sites internet utilisent des solutions tierces de Captcha, ouvrant la porte au traçage des utilisateurs notamment par des géants comme Google.
- Les Captchas les plus répandus sont très, mais alors vraiment très pénibles pour les humains qui eux n’ont rien demandé, au point de décourager certains utilisateurs de persévérer pour utiliser votre application.
- En particulier, les utilisateurs en situation de handicap peuvent être d’emblée exclus par certains de ces dispositifs.
- Par effet de rebond, l’utilisation de Captchas peut avoir un impact négatif sur votre taux de conversion.
Pour répondre à ces problématiques, nous allons voir qu’il est possible d’implémenter une solution maison qui allie le meilleur des deux mondes : se prémunir contre les robots, mais ne pas trop ennuyer ses utilisateurs et ne pas permettre à une solution tierce de tracer ces derniers.
Implémentation avec Symfony
La souplesse du framework Symfony va nous permettre de réaliser une solution maison évolutive.
Prérequis
L’exemple ci-dessous est conçu avec Symfony 3.4+ avec autowire et autoconfig activés, le code peut néanmoins être adapté pour fonctionner avec des versions antérieures.
Objectif
Nous allons créer un nouveau FormType qui proposera à vos utilisateurs de répondre à une question simple. Ce FormType pourra ensuite être ajouté à n’importe lequel de vos formulaires qui s’en trouvera instantanément sécurisé.
Les questions posées seront de ce type :
- Quelle est la première lettre du mot RUBIGINEUX ?
- Quelle est la seconde consonne du mot FLAVESCENT ?
- Quelle est la dernière voyelle du mot AMPHIGOURI ?
L’utilisateur peut très facilement identifier la bonne réponse, sans même avoir besoin de faire le moindre calcul mathématique. La saisie de la réponse est très rapide : elle tient en un seul caractère.
Sommaire
- Création d’un service “dictionnaire de mots”
- Création des services de génération des questions
- Création d’un CaptchaType
- Création d’un thème Twig pour le CaptchaType
- Gestion de l’internationalisation
- Utilisation dans un formulaire
Création d’un service “dictionnaire de mots”
Il peut être utilise d’isoler le dictionnaire de mots du reste du code, simplement pour pouvoir le remplacer facilement si besoin. Allons-y.
Note : dans cet exemple il s’agit de mots méconnus et insolites de la langue française. Aucun des mots ne comporte de caractères accentués. Seuls des mots d’au moins 5 lettres ont été retenus.
Création des services de génération des questions
Nous allons maintenant mettre en place plusieurs services pour générer les questions/réponses. Nous avons vu que nous allons poser plusieurs types de questions : position d’une lettre, d’une voyelle, ou d’une consonne dans un mot. Chacun de ces types de question aura son propre service.
Commençons par mettre en place une interface (au sens programmation orientée objet) :
Nous pouvons maintenant implémenter les services pour les différents types de questions.
Vous pouvez reprendre les types de questions de votre choix, ou implémenter vos propres types de questions.
Création d’un CaptchaType
Maintenant, nous pouvons utiliser ces services de génération de questions directement dans le FormType qui sera responsable d’afficher celles-ci sous la forme d’un champ texte. Grâce au concept des services taggués de Symfony, nous allons injecter tous les services de génération de questions dans le FormType qui choisira l’un d’entre eux au hasard.
La session est également nécessaire afin de pouvoir stocker la réponse à l’initialisation du formulaire, puis pour contrôler la validité de la réponse saisie par l’utilisateur à la soumission de ce même formulaire. Le FormType assurera la validation de la réponse grâce à la méthode validateCaptcha qui sera exécutée lors de la validation Symfony.
Voici maintenant comment configurer l’injection des services de génération des questions dans le fichier services.yaml :
Création d’un thème Twig pour le CaptchaType
Créons le thème qui sera utilisé pour afficher le champ Captcha :
A noter : l’exemple utilise Bootstrap (compatible version 3+).
Le champ utilisé pour saisir la réponse à la question est de type password, lorsque le champ obtiendra le focus, il sera automatiquement transformé en champ texte, ceci afin de perturber les robots qui ne s’attendent pas à ne devoir saisir qu’un seul caractère dans un champ password.
Il faut ensuite déclarer le thème personnalisé Twig dans la configuration :
Gestion de l’internationalisation
Le service de génération des questions se base sur des clés de traduction. Ajoutons ces traductions :
Votre Captcha est désormais prêt à l’emploi !
Utilisation dans un formulaire
Il vous reste maintenant à ajouter votre nouveau champ Captcha aux formulaires que vous souhaitez sécuriser comme dans l’exemple ci-dessous :
Si vous souhaitez utiliser le captcha seul, il suffit de créer un formulaire avec un unique champ CaptchaType.
L’utilisation de la validation Symfony (c’est à dire l’appel à $form->isValid() dans le contrôleur) va vérifier que la réponse fournie par l’utilisateur est correcte. Le formulaire sera invalide dans le cas contraire.
Le mot de la fin
Vous pouvez maintenant sécuriser vos formulaires sans irriter vos utilisateurs ni reposer sur une quelconque solution tierce avide de collecter des données.
La solution est très évolutive, car il est possible de changer de dictionnaire de mots mais aussi d’ajouter ou de retirer des implémentations de CaptchaInterface afin d’augmenter la diversité des questions proposées.
N’hésitez pas à me faire vos retours dans les commentaires.
Bibliographie
Le test de Turing inversé, le principe derrière les Captchas : https://en.wikipedia.org/wiki/Reverse_Turing_test
Créer des FormType Symfony personnalisés : https://symfony.com/doc/current/form/create_custom_field_type.html
Les services taggués de Symfony : https://symfony.com/doc/current/service_container/tags.html
Créer des thèmes pour les formulaires Symfony : https://symfony.com/doc/current/form/form_themes.html
Le système d’internationalisation de Symfony : https://symfony.com/doc/current/translation.html
Découvrez le travail de la quadrature du net : https://www.laquadrature.net/
Photographie : Rock’n Roll Monkey via Unsplash
Remerciements
Merci à Javier Eguiluz d’avoir mentionné cet article sur le blog de Symfony :
https://symfony.com/blog/a-week-of-symfony-751-17-23-may-2021