Sommaire
Un captcha fait payer aux humains le coût des robots. Pour un formulaire de contact, trois mesures simples suffisent presque toujours.
Le champ piège
Un champ invisible pour les humains, mais présent dans le HTML. Un robot qui remplit tout le formulaire se dénonce. Attention à l’accessibilité : le champ doit être retiré de l’ordre de tabulation et ignoré par les lecteurs d’écran.
<div aria-hidden="true" className="absolute -left-[9999px]">
<label htmlFor="website">Ne pas remplir</label>
<input id="website" name="website" tabIndex={-1} autoComplete="off" />
</div>Limiter le débit
Une fenêtre glissante par adresse IP, en mémoire : cinq messages par heure. Sur une instance unique, pas besoin de Redis.
const WINDOW_MS = 60 * 60 * 1000
const hits = new Map<string, number[]>()
export function allow(ip: string, now = Date.now()): boolean {
const recent = (hits.get(ip) ?? []).filter((time) => now - time < WINDOW_MS)
if (recent.length >= 5) return false
hits.set(ip, [...recent, now])
return true
}Et derrière un proxy ?
L’adresse vue par l’application est celle du proxy. Il faut lire X-Forwarded-For, mais uniquement si la requête vient bien du proxy de confiance.
Le délai minimal
Un humain met plus de trois secondes à écrire un message. Un horodatage signé, glissé dans le formulaire au rendu, permet de rejeter les envois trop rapides sans rien stocker.
Bilan
- L’essentiel des envois automatisés arrêté dès les premières semaines
- Aucun faux positif signalé
- Aucune dépendance externe
- #API
- #Sécurité



