Table des matières :
- Là où le spam frappe vraiment sur PrestaShop 9 (et pourquoi le cœur n’aide pas)
- reCAPTCHA en 2026 : v2, v3, contraintes techniques et conformité
- Module reCAPTCHA gratuit pour PrestaShop 9 : ce qu’il doit faire (et comment le faire proprement)
- Alternatives à reCAPTCHA : Turnstile, hCaptcha, Friendly Captcha (et leurs effets de bord)
- Alternatives « anti-spam » sans CAPTCHA : ce qui marche, ce qui casse, ce qui se mesure
- Déploiement sur PrestaShop 9 : instrumentation, seuils, et matrice de décision
Là où le spam frappe vraiment sur PrestaShop 9 (et pourquoi le cœur n’aide pas)
PrestaShop 9 n’embarque toujours pas de mécanisme anti-spam natif et générique côté front-office. On se retrouve donc avec une collection de formulaires hétérogènes (contact, création de compte, login, reset mot de passe, inscription newsletter selon modules, avis produits selon stack) qui n’exposent pas tous des hooks « propres » pour injecter une vérification. Le résultat est prévisible : dès que la boutique est indexée et crawlée, des bots balayent /contact-us, /authentication, /password-recovery et les endpoints POST correspondants.
Les impacts ne sont pas « juste » des mails de contact inutiles. Sur des boutiques à trafic moyen, on observe souvent une inflation de la table ps_customer (comptes poubelles), des logs applicatifs pollués, des queues SMTP saturées et des signaux de délivrabilité dégradés (hausse du taux de bounce/complaints). Côté perfs, ce bruit déclenche des traitements coûteux (création de client, envoi d’email, génération de token) et peut amplifier un problème de CPU/PHP-FPM déjà limite. Si vous avez déjà eu des 503 sporadiques, vous savez que le spam devient un multiplicateur de panne ; il faut le corréler avec votre supervision (voir Monitoring PrestaShop : KPI e-commerce, paiements et prévention des erreurs 503).
Pour objectiver le problème (et éviter le « on a l’impression que… »), deux vérifications rapides donnent souvent une photo très parlante :
- Corréler les pics de POST sur les routes sensibles avec les pics de latence/erreurs (logs Nginx/Apache + logs PHP + métriques PHP-FPM).
- Mesurer l’effet base de données : si la création de comptes est ciblée, vous verrez un volume inhabituel de créations récentes, souvent avec des patterns (domaines email jetables, prénoms aléatoires, pays incohérents).
Exemple de requêtes “diagnostic” (à adapter selon votre schéma/activité) :
-- Comptes créés sur 24 h (utile pour repérer une montée brutale)
SELECT COUNT(*) AS nb, DATE(date_add) AS jour
FROM ps_customer
WHERE date_add >= (NOW() - INTERVAL 7 DAY)
GROUP BY DATE(date_add)
ORDER BY jour DESC;
-- Domaines email les plus fréquents (repérage de patterns)
SELECT SUBSTRING_INDEX(email, '@', -1) AS domaine, COUNT(*) AS nb
FROM ps_customer
WHERE date_add >= (NOW() - INTERVAL 7 DAY)
GROUP BY domaine
ORDER BY nb DESC
LIMIT 20;
Mini-scénario courant (et très “terrain”) : une boutique FR/UE commence à être mieux référencée, puis reçoit en quelques jours des centaines de créations de comptes. Résultat : emails de bienvenue envoyés en masse, augmentation des bounces, puis certains fournisseurs (ou votre relais SMTP) durcissent la réputation IP/domaine. Même si vous “nettoyez” la base ensuite, le dommage délivrabilité peut persister.
Autre point rarement traité : le spam « applicatif » n’est pas seulement humain vs bot, c’est aussi du trafic automatisé qui cherche des failles (paramètres inattendus, encodages, payload XSS/SQLi). Les formulaires sont des vecteurs idéaux pour injecter et tester des charges. Et quand un module anti-spam est mal conçu (override agressif, validation fragile, dépendance JS bloquante), vous gagnez un nouveau point de défaillance. D’où une règle simple : en PrestaShop 9, un anti-spam doit être conçu comme une brique de sécurité et comme une brique de fiabilité (timeouts, failover, logs).
reCAPTCHA en 2026 : v2, v3, contraintes techniques et conformité
reCAPTCHA n’est pas un produit unique mais une famille. v2 (checkbox / challenge) impose une interaction utilisateur et se valide via un token renvoyé au serveur. v3 ne présente (théoriquement) aucune interaction : le navigateur exécute un script, reCAPTCHA renvoie un score, et l’application décide de bloquer/autoriser selon un seuil (documentation officielle reCAPTCHA v3 : https://developers.google.com/recaptcha/docs/v3).
Dans la pratique e-commerce, gardez en tête une nuance importante : v3 n’est pas un “anti-bot” tout-en-un, c’est un signal. Sans stratégie (seuil + fallback + rate-limit), v3 seul finit souvent en :
- faux positifs (utilisateurs réels bloqués : réseaux d’entreprise, VPN, navigateurs durcis),
- faux négatifs (bots modernes qui exécutent JS et ressemblent à un navigateur normal).
Techniquement, les trois points qui cassent des intégrations sont récurrents :
1) La validation serveur : vous devez appeler https://www.google.com/recaptcha/api/siteverify côté serveur, avec un timeout court (typiquement 1–2 s) et une gestion de panne (DNS/timeout). Si vous faites du « fail-closed » (refus si Google ne répond pas), vous introduisez un SPOF externe sur des parcours critiques (création de compte / checkout). Si vous faites du « fail-open » (acceptation si panne), vous devez compenser avec rate limit/WAF.
Un compromis souvent réaliste : fail-open sur les parcours qui doivent rester disponibles (ex : “mot de passe oublié”), mais durcir via rate limit et logs, puis fail-closed sur les formulaires non critiques (ex : avis produit, formulaire contact) si vous subissez une attaque massive.
2) La cohérence action/score (v3) : sans une vraie stratégie de seuil et de « replay » (ex : repasser en challenge v2 si score faible), vous allez bloquer des utilisateurs légitimes ou laisser passer des bots. La seule approche sérieuse est data-driven : mesurer le score, corréler avec le taux de fraude/spam, puis ajuster.
Sur v3, pensez aussi à exploiter ce que le fournisseur renvoie quand c’est disponible (selon versions/intégrations) : action attendue, hostname, timestamp. Ça aide à détecter une mauvaise intégration (token réutilisé, action incohérente, token provenant d’une autre page).
3) La conformité : reCAPTCHA implique un appel à des domaines tiers Google et, selon le mode, des traceurs et un transfert de données. La CNIL rappelle que les traceurs tiers nécessitent un cadre de consentement et une information claire (voir https://www.cnil.fr/fr/cookies-et-autres-traceurs). En pratique, sur un front-office UE, votre intégration doit prévoir un chargement conditionnel (après consentement) ou assumer que la formulaire ne fonctionne pas sans acceptation — ce qui a un impact UX/conversion.
Point opérationnel souvent oublié : documentez le comportement “sans consentement” (ex : affichage d’un message « Activez les cookies pour envoyer le formulaire ») et mesurez son impact (taux d’abandon sur /contact ou /authentication).
Module reCAPTCHA gratuit pour PrestaShop 9 : ce qu’il doit faire (et comment le faire proprement)
« Gratuit » en PrestaShop 9 veut souvent dire : module communautaire, module interne, ou fork d’un module legacy. Le problème n’est pas le prix, c’est la dette technique. Votre checklist doit être plus stricte que pour un module fonctionnel, parce que vous mettez ce module sur des endpoints exposés et dans le chemin critique.
Premier filtre : éviter les overrides. Un module anti-spam qui override AuthController, Customer, ou des classes Symfony du Back Office vous garantit des régressions à la prochaine MAJ. Si vous avez besoin de cadrer ce point, partez des principes détaillés dans Module PrestaShop sans override : méthode de cadrage, tests et livraison du code.
Deuxième filtre : gestion des clés et multiboutique. Les modules bricolés stockent trop souvent SITE_KEY et SECRET_KEY sans préfixe, ou pire les écrivent en clair dans un fichier. Utilisez la configuration PrestaShop, mais correctement : préfixe systématique (MYMOD_RECAPTCHA_SITEKEY) et compatibilité multiboutique (valeurs par shop si nécessaire). Pour éviter de polluer/écraser des clés existantes, appliquez la méthode décrite dans PrestaShop modules : préfixer les clés Configuration sans supprimer l’existant. Et surtout : ne stockez pas d’état dynamique (compteurs, tokens par session) dans ps_configuration — c’est un anti-pattern qui finit en latence et en verrouillages ; voir PrestaShop configuration : éviter l’état panier dans la table ps_configuration.
Troisième filtre : qualité de packaging. Même un module interne doit passer un minimum de conformité : namespaces, compatibilité PHP, absence d’accès direct non protégé, pas de exit; en plein front. Exécutez-le en CI avec le validator officiel (voir ps-validator : intégration CI/CD du Validator PrestaShop en terminal). Un module anti-spam est aussi un bon candidat pour tests end-to-end (Playwright/Cypress) sur les pages sensibles : s’il casse la création de compte, vous ne le verrez pas dans un simple test unitaire.
Checklist pratique (spécifique “anti-spam sur endpoints critiques”) avant mise en prod :
- Le module ne casse pas le formulaire si le JS ne charge pas (au minimum : message clair + fallback).
- Les timeouts réseau sont bornés (connect + total), et le module ne bloque pas un worker PHP-FPM trop longtemps.
- Les erreurs sont observables (logs structurés, codes de raisons stables).
- La validation serveur vérifie au minimum
successet refuse les payloads invalides (JSON absent, HTTP != 200). - En v3, la réponse est contrôlée (action attendue, seuil score) et un fallback est prévu.
Voici un squelette minimal (testé en PrestaShop 9.1/9.2 avec PHP 8.2/8.3) pour une validation serveur reCAPTCHA v2/v3. L’exemple ci-dessous utilise cURL (à préférer à file_get_contents() quand allow_url_fopen est désactivé), avec timeout strict et parsing défensif :
private function verifyRecaptcha(string $token, ?string $remoteIp = null): array
{
$secret = (string) Configuration::get('MYMOD_RECAPTCHA_SECRET');
if ($secret === '' || $token === '') {
return ['ok' => false, 'reason' => 'missing_secret_or_token'];
}
$ch = curl_init('https://www.google.com/recaptcha/api/siteverify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 1,
CURLOPT_TIMEOUT => 2,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => $secret,
'response' => $token,
'remoteip' => $remoteIp,
]),
]);
$raw = curl_exec($ch);
$err = curl_error($ch);
$http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($raw === false || $http !== 200) {
return ['ok' => false, 'reason' => 'verify_failed', 'detail' => $err, 'http' => $http];
}
$data = json_decode($raw, true);
if (!is_array($data) || empty($data['success'])) {
return ['ok' => false, 'reason' => 'challenge_failed', 'data' => $data];
}
// v3: exploiter score/action si présents
return ['ok' => true, 'data' => $data];
}
Point clé : la fonction retourne une structure riche (raison, HTTP, payload). Ne vous contentez pas d’un booléen, sinon vous ne saurez jamais si vous bloquez parce que « bot » ou parce que « Google indisponible ». Et ne logguez jamais le secret, évidemment.
Deux recommandations “qualité prod” à ajouter très souvent dans la vraie vie :
- Sur v3, validez l’
actionattendue (si vous l’utilisez) : un token “login” ne devrait pas valider un “contact”. C’est une protection simple contre des erreurs d’intégration et certains scénarios de réutilisation. - Prévoir un mode dégradé explicite : par exemple, si
verify_failed, déclencher un rate limit plus strict côté serveur/edge plutôt que de bloquer aveuglément tout le monde.
Alternatives à reCAPTCHA : Turnstile, hCaptcha, Friendly Captcha (et leurs effets de bord)
Si votre contrainte principale est la conformité et la réduction de dépendance à Google, Cloudflare Turnstile est généralement l’alternative la plus simple à intégrer (surtout si vous utilisez déjà Cloudflare en proxy). La documentation officielle est ici : https://developers.cloudflare.com/turnstile/. En pratique, l’intégration est proche de reCAPTCHA : widget/JS côté client + endpoint de vérification serveur. L’avantage opérationnel : vous pouvez souvent combiner Turnstile avec des protections edge (WAF, rate limiting) dans le même fournisseur.
hCaptcha (https://docs.hcaptcha.com/) est une autre option fréquente. Attention toutefois à l’écosystème module : beaucoup d’intégrations PrestaShop 1.7/8 reposent sur des overrides des templates d’authentification, donc sources de régressions en PrestaShop 9. Sur le plan technique, hCaptcha impose aussi des appels tiers et une validation serveur ; sur le plan UX, vous retombez vite sur des challenges visuels, donc accessibilité discutable et friction (ce qui peut compter sur mobile).
Friendly Captcha est souvent cité pour son approche “proof-of-work” côté navigateur (moins de puzzles). C’est pertinent sur des formulaires à faible volume, mais ce n’est pas « gratuit » et cela peut ajouter un coût CPU client (mobile bas de gamme). Sur une boutique, ça peut être acceptable sur /contact mais plus discutable sur une création de compte pendant un pic de trafic.
Comparatif rapide (à lire comme une grille “décision”, pas comme une vérité universelle) :
| Option | Dépendance tiers | Friction UX | Risque “SPOF externe” | Points d’attention (PrestaShop 9) |
|---|---|---|---|---|
| reCAPTCHA v2 | Élevée | Moyenne à forte | Oui | Consentement/chargement conditionnel, fallback si JS bloqué |
| reCAPTCHA v3 | Élevée | Faible (en théorie) | Oui | Stratégie de seuil + fallback indispensable |
| Turnstile | Élevée | Faible à moyenne | Oui | Souvent plus simple si Cloudflare déjà en place |
| hCaptcha | Élevée | Souvent forte | Oui | Modules legacy + accessibilité/challenges |
| Friendly Captcha | Élevée | Faible à moyenne | Oui | Coût client, modèle payant selon usage |
Dernier point, souvent ignoré jusqu’au jour où ça casse en prod : CSP. Quel que soit le fournisseur, il faudra ouvrir script-src, frame-src et parfois connect-src sur des domaines tiers. Si vous durcissez votre politique, documentez-la et versionnez-la ; sur PrestaShop, beaucoup de gens commencent par verrouiller frame-ancestors, mais une vraie politique CSP va plus loin (voir CSP frame-ancestors : empêcher le clickjacking et l’intégration non autorisée).
Conseil simple : faites une liste explicite des domaines autorisés “CAPTCHA”, et testez-la en staging avec Content-Security-Policy-Report-Only avant d’appliquer en dur.
Alternatives « anti-spam » sans CAPTCHA : ce qui marche, ce qui casse, ce qui se mesure
Le CAPTCHA n’est pas obligatoire pour réduire le spam de façon drastique, surtout si votre problème est du bot générique plutôt que du fraudeur ciblé. Le triptyque classique (et efficace) : honeypot + temporisation + validation comportementale. Honeypot : un champ caché (CSS + aria-hidden, jamais display:none si vous craignez des lecteurs d’écran) que seuls les bots remplissent. Temporisation : refuser un POST soumis « trop vite » (ex : < 2 s après affichage), ce qui coupe une partie du headless. Comportement : vérifier que des champs critiques (email) respectent des patterns réalistes et que l’User-Agent n’est pas vide.
Deux précautions importantes pour que ces techniques “sans CAPTCHA” restent fiables :
- Ne pénalisez pas l’accessibilité : une temporisation trop agressive peut gêner les utilisateurs qui utilisent l’auto-fill, les lecteurs d’écran, ou qui naviguent très vite. C’est pour ça qu’il faut mesurer les faux positifs (et pas seulement “le spam diminue”).
- Ne vous reposez pas sur un seul signal : honeypot seul = contournable. Temporisation seule = contournable. L’intérêt, c’est la combinaison + un filet réseau (rate limiting).
Ce type de protection a un avantage majeur : aucun appel tiers, donc aucune dépendance réseau, et pas d’effet direct RGPD. En revanche, ça ne suffit pas contre des bots qui exécutent JS et simulent un utilisateur. Il faut donc ajouter un contrôle au niveau HTTP : rate limiting (par IP, par session, par route), idéalement en edge (CDN/WAF) ou au niveau Nginx/HAProxy. Pour le cadrage, transposez les mêmes principes que pour une API publique : quotas, fenêtre glissante, et réponse explicite 429 (voir API Rate Limits : comprendre les quotas, headers de limite et erreurs 429).
Exemple concret (Nginx) : limiter les POST vers l’authentification et le contact. Ça ne remplace pas un CAPTCHA, mais ça baisse immédiatement le volume et protège PHP-FPM.
limit_req_zone $binary_remote_addr zone=form_limit:10m rate=10r/m;
server {
location ~* ^/(authentication|contact-us|password-recovery) {
if ($request_method = POST) {
limit_req zone=form_limit burst=5 nodelay;
}
try_files $uri $uri/ /index.php?$args;
}
}
Note PrestaShop (important en boutique FR multi-langues) : selon vos URLs réécrites et langues, les chemins peuvent varier. Le principe reste : limiter sur les POST vers les routes “formulaires”, et si besoin, matcher aussi les versions avec préfixe langue (/fr/…, /en/…) ou les routes réelles après rewrite.
À ce stade, la vraie question n’est pas « CAPTCHA ou pas CAPTCHA », mais où vous placez la logique. Si vous l’implémentez uniquement dans PrestaShop, chaque POST spam traverse votre stack PHP + MySQL avant d’être rejeté. Si vous déplacez une partie au niveau edge (WAF/rate-limit), vous réduisez le coût dès le front. Et si vous cachez mal (ex : pages HTML mises en cache qui embarquent des tokens CSRF expirés), vous cassez des formulaires : gardez une cohérence avec votre stratégie de cache/CDN (voir Cache PrestaShop : stratégie 2026 OPcache, Redis, Varnish et CDN).
Déploiement sur PrestaShop 9 : instrumentation, seuils, et matrice de décision
Sans instrumentation, un module reCAPTCHA gratuit (ou n’importe quel anti-spam) se résume à « on l’a installé et on espère ». Ce qui marche réellement : logguer les refus avec une taxonomie stable (challenge_failed, verify_timeout, rate_limited, honeypot_hit), puis suivre des métriques : taux de refus par route, taux de faux positifs (tickets SAV « je ne peux pas créer de compte »), impact sur le taux de conversion (funnel). Les KPI doivent vivre dans votre monitoring au même titre que les 503 et la latence applicative (voir aussi le cadrage sur le suivi des KPI e-commerce et des erreurs 503).
Un format de log simple et exploitable (même sans SIEM) consiste à logguer en JSON une ligne par décision anti-spam, par exemple :
{
"event": "antispam_decision",
"route": "authentication",
"decision": "blocked",
"reason": "verify_failed",
"http_status": 200,
"provider": "recaptcha",
"shop_id": 1
}
L’objectif n’est pas de tout stocker (attention aux données personnelles), mais de pouvoir répondre à trois questions en 10 minutes :
- Qu’est-ce qui est bloqué, où, et depuis quand ?
- Est-ce un problème “bots” ou un problème “provider indisponible / CSP / consentement” ?
- Quel est l’impact sur les utilisateurs légitimes (support + conversion) ?
Pour reCAPTCHA v3, ne choisissez pas un seuil « au feeling ». Stockez (temporairement) le score et l’action dans un log applicatif (pas dans ps_configuration), puis faites une analyse simple sur 7–14 jours : distribution des scores sur utilisateurs légitimes vs spams confirmés. Typiquement, un seuil trop haut (ex : 0.7) peut bloquer une population entière (VPN, mobile) ; un seuil trop bas (ex : 0.1) ne sert à rien. La stratégie robuste est en deux temps : (1) v3 pour scorer, (2) fallback v2/Turnstile en challenge au-dessous d’un seuil, (3) rate-limit en dernier filet.
Matrice de décision pragmatique (à adapter) :
- Boutique UE, contrainte RGPD forte, besoin de minimiser les tiers : honeypot + temporisation + rate limiting edge. Ajoutez Turnstile si le spam persiste.
- Spam massif sur formulaire contact : Turnstile ou reCAPTCHA v2 sur contact uniquement + rate limiting Nginx/WAF. Vous évitez de mettre un tiers sur le parcours d’achat.
- Fraude ciblée / bots sophistiqués sur création de compte : v3 + fallback challenge + contrôles server-side (vérif MX basique, blocage domaines jetables, quotas par IP), plus observabilité.
Dernier piège : la compatibilité PrestaShop 9 est moins une question de PHP que de cycle de release. Un module anti-spam doit être testé à chaque update core, comme un module de paiement. Automatiser les tests et vérifier la conformité du package vous évite des surprises en prod : ps-validator en CI, staging, et déploiement contrôlé. C’est banal, mais c’est exactement là que les « modules gratuits » deviennent coûteux quand ils cassent un flux critique.
