Captcha (core/security/captcha)
Desafio visual simples (código numérico distorcido, renderizado como PNG) para formulários públicos — sem depender de nenhum serviço externo (Google reCAPTCHA, hCaptcha, etc). Zero configuração de conta, zero chave de API, zero chamada de rede para o navegador do visitante bloquear ou atrasar.
Uso pronto — captcha.Store
import "kyrux/core/security/captcha"
captchaStore := captcha.NewStore(fw.Sessions)
router.Path("GET", "/captcha/image", captchaStore.ImageHandler(), "captcha_image"),
// no handler de POST do formulário:
if !captchaStore.Verify(ctx, ctx.Request.FormValue("captcha_answer")) {
// código incorreto — mostre erro e não processe o formulário
}
No template:
<img src="{{ url "captcha_image" }}" alt="Código de verificação" id="captchaImg">
<input type="text" name="captcha_answer" maxlength="5" inputmode="numeric" required>
ImageHandler gera um código novo a cada requisição (útil para um "gerar
outro" no front — troque o src da imagem com um cache-buster, ex:
?t=Date.now()) e guarda na sessão do visitante, substituindo o anterior.
Verify confere a resposta contra o código da sessão e o consome (uso
único) independente do resultado — sempre precisa de uma imagem nova para
uma nova tentativa.
Primitivas de baixo nível
Para guardar o código em outro lugar que não sessão (ex: banco, num fluxo sem cookie):
code, err := captcha.New() // código aleatório de captcha.CodeLength dígitos
png, err := captcha.PNG(code) // imagem PNG distorcida do código
Como funciona a imagem
Fonte bitmap 5x7 própria (só dígitos 0-9, sem ambiguidade visual tipo 0/O
ou 1/I/l), desenhada com image/image/png da stdlib — sem
golang.org/x/image nem nenhuma outra dependência de terceiros. Ruído de
fundo (linhas e pontos aleatórios) e leve inclinação por caractere
dificultam OCR automatizado simples.