Dans ce tutoriel je vous propose de découvrir comment créer un système de captcha personnalisé en PHP & JavaScript. L'objectif est de créer un mini-puzzle sur lequel l'utilisateur devra placer une pièce au bon endroit pour confirmer qu'il n'est pas un robot.
Sommaire
00:00 Fonctionnement général
03:10 Création des interfaces
06:09 Implémentation du Puzzle
21:20 Génération de l'image (captcha)
34:41 JavaScript, Custom Element
53:00 Intégration dans Symfony
Pourquoi ?
Avant de commencer on peut se demander pourquoi utiliser un système personnalisé alors qu'il existe des solutions toutes faites comme ReCaptcha de Google ou HCaptcha.
Le problème de ces solutions, c'est que ce sont des solutions qui sont tellement généralisées que des services se sont créés autour pour les résoudre de manière plus ou moins optimisée.
Le second problème est la souveraineté des données car pour intégrer ces systèmes de captcha vous devez en général intégrer du JavaScript tiers dans votre page qui peut potentiellement avoir accès à des informations sensibles sur vos utilisateurs (email, nom d'utilisateur et mot de passe).
En revanche, une solution maison va impliquer plus de travail et de tests pour obtenir un résultat qui soit satisfaisant (le moins contraignant pour les utilisateurs tout en étant efficace). Il se pose aussi le problème de l'accessibilité que l'on choisira dans notre cas de gérer à la main si nécessaire.
Principe général
Le principe du captcha est de générer un problème avec une solution qui devra être deviné par un humain. Pour notre cas on va générer une position en X et en Y. On associera à cette valeur une clef que l'on enverra dans le formulaire utilisateur. Cette clef sera ensuite utilisée pour générer un problème difficile à résoudre pour un robot (dans notre cas une image avec un trou à la position indiquée). En complétant le problème l'utilisateur va générer une position que l'on pourra ensuite comparer côté serveur pour savoir si la réponse est satisfaisante et savoir si l'utilisateur est un robot ou non.
sequenceDiagram
Server->>Server: Génère une clef
Server->>Client: Formulaire HTML avec clef
Client->>CaptchaService: Envoie la clef
CaptchaService->>CaptchaService: Génère le problème
CaptchaService->>Client: Renvoie le problème
Client->>Client: Résoud le problème
Client->>Server: Soumet clef + solution
Server->>Server: Valide solution
L'interface
Pour notre système on va donc avoir besoin de 2 éléments :
Un système permettant de générer et vérifier une clef
interface ChallengeInterface
{
public function generateKey(): string;
public function verify(string $key, string $anwser): bool;
public function getSolution(string $key): mixed;
}
Un système permettant de générer le problème à partir de la clef
interface ChallengeGenerator
{
public function generate(string $key): Response;
}
L'implémentation de ces 2 interfaces va dépendre du type de problème que vous souhaitez soumettre à l'utilisateur.