WordPress

Jak zabezpieczyć formularz kontaktowy WordPress przed spamem

Formularz WordPress zasypany spamem? Poradnik: reCAPTCHA, honeypot, Turnstile, Akismet i inne metody antyspamowe. Porównanie rozwiązań i konfiguracja krok po kroku.

DDawid Penkala
Zaktualizowano: 10 min czytania
Bezpieczeństwo formularza kontaktowego na stronie WordPress

U nowego klienta pierwszym objawem, że coś jest nie tak, bywa jeden mail: „dostajemy po 200 wiadomości dziennie z formularza, większość to śmieci”. Logujemy się, patrzymy, zwykle widzimy to samo: Contact Form 7 z domyślną konfiguracją, reCAPTCHA v2 (checkbox „nie jestem robotem”), może Akismet z expired kluczem. Rozwiązanie zajmuje nam godzinę, ale zasady, które stosujemy — warto znać.

Honeypot pierwszy, zawsze

Najprostsza i najskuteczniejsza obrona przeciwko 90% botów — pole, którego nie widzi człowiek, ale bot wypełnia automatycznie.

<div style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
  <label for="website">Nie wypełniaj tego pola</label>
  <input type="text" name="website" id="website" tabindex="-1" autocomplete="off">
</div>

Po stronie serwera: jeśli pole website ma wartość → odrzuć. Koszt: 0 zł, 0 impaktu na UX, nie wysyła danych do Google/Cloudflare, kompatybilne z RODO bez zgody użytkownika.

Efektywność: eliminuje większość dumb botów (te, które po prostu wypełniają wszystkie inputy). Nie zatrzyma inteligentnych (headless Chrome z custom skrypcją), dla nich potrzebne drugie zabezpieczenie.

W Contact Form 7 używamy Honeypot for Contact Form 7. WPForms ma to w pakiecie Pro. Fluent Forms — wbudowane.

Drugie zabezpieczenie: Cloudflare Turnstile (zamiast reCAPTCHA)

Od dwóch lat nie instalujemy u klientów reCAPTCHA. Powodów trzy:

  1. RODO. reCAPTCHA wysyła ciasteczka i fingerprint użytkownika do Google zanim kliknie formularz. Prawnicy RODO uważają to za transfer danych do USA bez wyraźnej zgody. Jeśli masz baner cookie „reCAPTCHA ładuje się dopiero po akceptacji” — OK. Większość stron go nie ma.
  2. UX. reCAPTCHA v2 to irytujące „zaznacz wszystkie mosty”. 20% użytkowników porzuca formularz.
  3. Koszt w LCP. reCAPTCHA ładuje ~100 KB JS przed interakcją.

Cloudflare Turnstile to free alternatywa, przezroczysta (żadnych challengy dla 99% userów), bez trackingu. Integracja w Contact Form 7 przez wtyczkę Simple Cloudflare Turnstile, w WPForms/Fluent Forms natywnie.

Konfiguracja w 5 minut:

  1. Zakładasz site w dash.cloudflare.com → Turnstile.
  2. Dostajesz site key i secret key.
  3. W wtyczce wklejasz oba klucze.
  4. Wybierasz tryb „Managed” (auto) lub „Invisible” (zupełnie niewidoczne).

Efektywność: ~95% botów filtrowanych bez interakcji użytkownika.

Akismet — dla content-level spam

Honeypot + Turnstile blokują 98% automatycznych botów. Reszta to często zwykły ludzki copy-paste („Promocja SEO tanie kliknięcia hit cena”) — wtedy zatrzymuje Akismet, który analizuje treść wiadomości i porównuje z globalną bazą spam.

Darmowy dla blogów osobistych, 9 $/mies dla firm. Plug in Contact Form 7 Akismet Integration robi resztę.

Uwaga compliance: Akismet też wysyła treść wiadomości do Automattic (USA). W politykach prywatności trzeba wymienić.

Rate limiting na poziomie Cloudflare

Jeśli serwis ma Cloudflare Pro (20 $/mies) albo Business, można dodać rule:

Jeśli path == /wp-admin/admin-ajax.php
AND requests na adres IP > 10 na minutęute
THEN challenge (CAPTCHA)

Zatrzymuje ataki bruteforce na poziomie edge, zanim request dotrze do PHP. Darmowy Cloudflare tego nie ma, ale free plan ma „Security Level = High” który działa pseudorandomowo.

Dla ostrzejszego zastosowanie (sklep WooCommerce z checkout) — własny Worker, który liczy requesty na adres IP w KV i blokuje powyżej progu. U jednego klienta robiliśmy własny mechanizm ograniczający liczbę żądań, który po 5 próbach w 60s rzucał 429 Too Many Requests. Atak DDoS na checkout spadł z 40 tys. req/s do zera.

Czego nie instalujemy

  • reCAPTCHA v2 checkbox — jak wyżej. UX katastrofa, RODO problem.
  • reCAPTCHA Invisible — lepsze niż checkbox, ale wciąż ten sam problem z danymi do Google.
  • Custom JS captchas („kliknij w czerwony kwadrat”) — dostępność (screen readery, klawiatura). Złe dla WCAG/EAA compliance.
  • Math captchas („2 + 3 = ?”) — boty nauczyły się rozwiązywać. Użytkownicy nie nauczyli się ich lubić.
  • Wtyczki “All-in-One spam” które robią wszystko naraz — zwykle robią wszystko źle. Wolimy 3 dedykowane wtyczki niż jedną „wszystko w jednym”.

Jak wygląda stack u klienta

Typowa konfiguracja dla formularza kontaktowego:

  1. Honeypot w samym formularzu (wtyczka lub kod w motywie).
  2. Cloudflare Turnstile jako widoczna ochrona (faktycznie niewidoczna dla 99% userów).
  3. Akismet dla content-level spam (tylko jeśli klient ma OK RODO).
  4. Rate limiting na poziomie Cloudflare (jeśli Pro).
  5. Log monitoring — raz na tydzień sprawdzamy logi wtyczki formularza. Podejrzane wzorce (ta sama treść z 20 IP) → dodajemy regułę do Cloudflare.
  6. Double opt-in dla formularzy zapisu na newsletter — brak spam’ów przez osoby trzecie (limit liczby żądań na same zapisy to inna sprawa).

Przy tym stacku spam w skrzynce spada z „setki dziennie” do „1–2 tygodniowo”. Całkowita eliminacja nie jest możliwa, bo 2% botów ma budżet na rozwiązywanie Turnstile’a ręcznie (tak, jest rynek Indonezji/Filipin gdzie ludzie rozwiązują captche za 2 $/godzinę). Dla tego ostatniego 2% — Akismet i manualne filtrowanie.

Konfiguracja Contact Form 7 step-by-step

CF7 jest stary, wolny, ładuje jQuery — nie polecamy na nowych stronach (wolimy WPForms Lite / Fluent Forms). Ale na legacy instalacjach CF7 można obronić:

[contact-form-7 id="123"]
  Imię: [text* your-name]
  Email: [email* your-email]
  Wiadomość: [textarea your-message]

  <!-- Honeypot -->
  [honeypot honeypot-field]

  <!-- Turnstile (po instalacji wtyczki) -->
  [cfturnstile]

  [submit "Wyślij"]
[/contact-form-7]

W Dodatkowych ustawieniach:

acceptance_as_validation: on
demo_mode: off

Testowanie

Po konfiguracji ZAWSZE test:

  1. Z innej przeglądarki / trybu incognito wyślij prawdziwy formularz — sprawdź, że trafia na skrzynkę.
  2. W DevTools → Network, wypełnij honeypot JS-em: document.getElementById('website').value = 'bot' i wyślij. Powinien być odrzucony.
  3. Wyłącz JavaScript i spróbuj wysłać — Turnstile powinien nie pozwolić (bo wymaga JS).
  4. Sprawdź, czy wiadomości nie trafiają do spamu maila — SPF/DKIM na domenie nadawcy + ewentualnie WP Mail SMTP z Postmarkiem/SendGridem.

Co gdy formularz jest ciągle zalany spamem

Jeśli mimo wszystkiego co wyżej spam dalej wchodzi, problem zwykle jest w:

  • IP frendly country — boty z Polski/Niemiec mogą omijać część filtrów Cloudflare (jesteś w lokalnym regionie dla nich). W Cloudflare dodaj limit żądań na IP na minutęute.
  • Formularz bez honeypota w motywie custom — wtyczki dodają CF7/WPForms, ale formularz w motywie nie ma. Trzeba dorzucić ręcznie.
  • Stary endpoint — ktoś kiedyś miał /kontakt-form.php i zapomniał go usunąć. Skaner Patchstack to pokaże.

Gdy trafia do nas klient z „nie wiem co zrobić, dalej spam” — zaczynamy od audytu wszystkich aktywnych formularzy na stronie i sprawdzenia ich ustawień. Darmowy audyt obejmuje m.in. sprawdzenie ochrony formularzy.


Dobrze skonfigurowany formularz ma prosty cel: filtr 98% botów bez irytowania człowieka. Jeśli masz reCAPTCHA v2 i 200 spamów dziennie — to nie kwestia „dodania jeszcze jednej wtyczki”, to zmiana podejścia.

Tagi:formularz WordPressantyspam WordPressreCAPTCHATurnstileContact Form 7RODO
Dawid Penkala
Dawid Penkala

Doświadczony WordPress Developer z ponad 14-letnim stażem w tworzeniu zaawansowanych stron i sklepów internetowych. Specjalizuje się w WordPressie, dedykowanych wtyczkach i motywach.

Więcej o autorze