Proteger un formulario público sin sesión ni cookie
Un sello firmado con HMAC que vence solo, no se puede fabricar y de paso delata a los robots por lo rápido que responden.
O problema
Un formulario abierto al público recibe envíos automáticos. Abrir una sesión para cada visitante solo por eso es caro y deja cookies que nadie pidió.
<?php
const SEMILLA = 'cambiar-por-un-secreto-largo';
function sello(): string {
$ts = time();
return $ts . '.' . hash_hmac('sha256', 'form|' . $ts, SEMILLA);
}
function sello_edad(string $sello): ?int {
[$ts, $firma] = array_pad(explode('.', $sello, 2), 2, '');
$esperada = hash_hmac('sha256', 'form|' . (int) $ts, SEMILLA);
if (!hash_equals($esperada, $firma)) return null; // fabricado o alterado
$edad = time() - (int) $ts;
return ($edad < 0 || $edad > 21600) ? null : $edad; // vence a las 6 horas
}
// En el formulario: <input type="hidden" name="sello" value="<?= sello() ?>">
$edad = sello_edad($_POST['sello'] ?? '');
if ($edad === null) exit('Formulario vencido. Recargá la página.');
if ($edad < 3) exit('Demasiado rápido para ser una persona.');
Por que está escrito assim
- El sello es la hora en que se sirvió el formulario más su firma HMAC. Sin la semilla, nadie puede fabricar uno válido.
- hash_equals compara en tiempo constante: no filtra información por cuánto tarda la comparación.
- Como la hora viaja firmada, el servidor sabe cuánto tardó la persona en responder sin guardar nada.
- Un envío en menos de tres segundos casi nunca es humano: es el filtro contra robots más barato que existe.
Poné el campo oculto en tu formulario y el bloque final al principio del script que lo recibe. Enviá apenas carga la página: debe rechazarlo por rápido.
El mismo sello sirve para varios envíos durante seis horas: frena robots, no reemplaza un límite de envíos por IP. Y la semilla va en un archivo de configuración fuera del repositorio.
Adapte ao seu caso com IA
O botão copia este prompt com o código colado abaixo. Substitua os colchetes pelo que é seu e cole no ChatGPT, Claude, Gemini ou Copilot.
Uso este sello HMAC en PHP para proteger un formulario público sin sesión. Agregale un campo trampa oculto (honeypot) y un límite de [CANTIDAD] envíos por IP por día guardado en [DÓNDE GUARDO: archivo, SQLite o MySQL]. Que los rechazos devuelvan mensajes distintos para una persona y silencio para un robot. PHP 8, sin frameworks.
Exemplo escrito e revisado à mão.
Comentários
Ainda não há comentários. O primeiro pode ser o seu.
Adaptou para algo seu?
Me conte o que resolveu com isto, ou o que faltou.