Proteção de APIs e formulários: o porteiro contra spam e abuso

Proteção de APIs e formulários: o porteiro contra spam e abuso

Atualizado: 12 min de leitura
  • segurança
  • rate-limiting
  • anti-spam
  • validação
  • api
  • turnstile

Um formulário de contato ou uma API pública sem controle é como um prédio sem porteiro: qualquer um entra, deixa lixo ou tenta forçar a porta. Spam, força bruta e scraping não são “ruído menor”: lotam caixas de entrada, consomem cota de email e podem derrubar um endpoint numa sexta à tarde.

Este artigo explica uma abordagem em camadas — o mesmo padrão que este portfólio usa em produção com Astro, e aplicável a Laravel e Node — para que uma pessoa não técnica entenda o porquê, e um técnico tenha checklist, ordem de checagens e erros a evitar.

Por que importa para o negócio

Cada lead falso custa tempo de vendas. Cada tentativa de login sem limite é uma loteria contra credenciais vazadas. Cada webhook ou endpoint “aberto” é superfície de abuso. Proteger não é paranoia: é manter o canal útil para humanos reais e caro para bots.

  • Caixa de entrada usável: menos spam = mais respostas a clientes reais.
  • Disponibilidade: rate limit evita que um script derrube o servidor.
  • Confiança: validar no servidor reduz lixo no CRM e tickets inventados.
  • Conformidade prática: menos PII de atacantes em logs e bases.

Conceitos-chave (simples + técnicos)

O porteiro em camadas

Nenhuma camada sozinha basta. O honeypot pega bots toscos; o rate limit freia o volume; o timing detecta envios desumanos; validação e sanitização cuidam do que entra; Turnstile adiciona atrito só quando preciso. Como um prédio: recepção, câmera, chave e alarme — não só uma placa de “proibido”.

CamadaO que bloqueiaResposta típica
Rate limitingVolume / força bruta429 + Retry-After
HoneypotBots que preenchem tudo200 silencioso (sem processar)
Form timingEnvios < ~3.5s400
Origin checkScripts cross-origin básicos403
TurnstileBots mais sofisticados400 se o token for inválido
Zod + sanitizarLixo e payloads estranhos400 com erros de campo

Rate limiting

Limita requests por IP (e, se aplicável, por usuário) numa janela de tempo. Em um só processo, memória basta; com várias réplicas é preciso Redis ou outro store compartilhado. Exemplos orientativos: login 5/min, reset de senha 3/hora, contato 5/min.

Honeypot e timing

O honeypot é um campo oculto (display: none ou fora da tela) que humanos não veem. Se chegar preenchido, rejeite em silêncio (200 sem processar) para não treinar o bot. O timing guarda um timestamp no render e rejeita envios mais rápidos que um humano razoável.

Validação, sanitização e origem

A validação do frontend melhora a UX; a do servidor é a que importa. Esquemas (Zod ou equivalente), strip de HTML em texto plano, comprimentos máximos e, em produção, checar Origin/Referer. Não é infalível, mas filtra muito ruído barato.

Guia prático: fluxo num endpoint

  1. Rate limit check → 429 se exceder.
  2. Honeypot check → 200 silencioso se o campo oculto tiver valor.
  3. Form timing check → 400 se for rápido demais.
  4. Origin check → 403 se a origem não for a do site.
  5. Turnstile (se configurado) → 400 se o token falhar.
  6. Validação com esquema → 400 com erros de campo.
  7. Sanitização → processar (email, CRM, fila).

Honeypot bem feito

  • Oculto com CSS, não com type="hidden" óbvio quando puder evitar.
  • Nome enganoso (website, company_url) — não honeypot.
  • tabindex="-1" e autocomplete="off"; não deve ser acessível acidentalmente a leitores de tela.
  • Se estiver preenchido: responder sucesso falso, não 403 explícito.

Cloudflare Turnstile

Quando o volume de spam justifica atrito extra, o Turnstile é leve e respeita privacidade frente a alternativas mais agressivas. TURNSTILE_SITE_KEY no cliente; TURNSTILE_SECRET_KEY só no servidor. O servidor verifica o token antes de processar.

Erros frequentes

  • Confiar só na validação do frontend.
  • Rate limit só no login, não no contato nem em endpoints públicos.
  • Honeypot visível, com label real, ou focável por teclado/leitores.
  • Responder 403 ao honeypot (o bot aprende e se adapta).
  • Logar payloads completos com emails e telefones (PII em logs).
  • Rate limit em memória com 3 réplicas (cada uma tem seu contador).
  • Mensagens de erro que revelam se um email “existe” no sistema.

Checklist de proteção

  • Lista de endpoints públicos sensíveis (login, contato, reset, webhooks).
  • Rate limit com limites documentados e Retry-After.
  • Honeypot + timing em formulários HTML.
  • Checagem Origin/Referer em produção.
  • Esquema de validação no servidor + sanitização.
  • Turnstile opcional quando o spam justificar.
  • Store compartilhado (Redis) se houver mais de uma réplica.
  • Logs sem PII desnecessária; métricas de 429/400 para detectar ataques.

Conecta com auditoria de segurança, cibersegurança e APIs REST .

Perguntas frequentes

O honeypot basta contra bots?

Não sozinho. Filtra bots básicos, mas convém combinar com rate limiting, timing e, em produção com muito spam, um CAPTCHA como Turnstile.

Onde aplicar rate limiting?

Em endpoints públicos: login, registro, reset de senha, formulários de contato, webhooks e APIs sem autenticação. Por IP e, se aplicável, por usuário autenticado.

Validar no frontend ou no backend?

Nos dois, mas o backend é obrigatório. O frontend melhora a experiência; o backend é a porta que não se pula com curl.

Turnstile ou reCAPTCHA?

Turnstile costuma ser mais leve e amigável à privacidade. reCAPTCHA funciona, mas depende do Google. Escolha conforme o stack e a política de privacidade do site.

Rate limiting em memória escala?

Para um único processo, sim. Com várias réplicas é preciso Redis ou outro store compartilhado; senão cada instância tem seu contador e o limite real se multiplica.