Voltar ao código PHP

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.

Este post ainda não está no seu idioma; você o vê em espanhol. O código é o mesmo.

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
<?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

  1. 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.
  2. hash_equals compara en tiempo constante: no filtra información por cuánto tarda la comparación.
  3. Como la hora viaja firmada, el servidor sabe cuánto tardó la persona en responder sin guardar nada.
  4. Un envío en menos de tres segundos casi nunca es humano: es el filtro contra robots más barato que existe.
Como testar

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.

Atenção

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.

O prompt
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.

Compartilhar

Comentários

Ainda não há comentários. O primeiro pode ser o seu.

Apenas texto, sem links. Não pedimos e-mail. Os comentários são revisados antes de serem publicados.

Adaptou para algo seu?

Me conte o que resolveu com isto, ou o que faltou.

Continue testando

Mais código

Ver todos
Darinel Ortega Online · respondo ao longo do dia
Hoje
Olá. Aqui eu não vendo nada: isto é para trocar conhecimento sobre tecnologia.
Escreva o que quiser — pode mandar texto, imagens ou documentos. As mensagens chegam ao meu console e eu respondo por lá.
Você está escrevendo fora do horário. Eu leio assim que o dia começar.

Conversa aberta para compartilhar conhecimento. As mensagens chegam ao meu console e eu respondo por lá.

Vamos marcar uma conversa

Escolha o dia e a hora que funcionem para você. Trinta minutos, sem discurso comercial.

Videochamada

Para uma videochamada, peça por aqui que eu te mando o link da sessão.