Zum Inhalt springen
Antisy

WordPress-Formular vor Bots schützen, ohne Plugin

Ein Antisy-Plugin für WordPress gibt es nicht: Die Einbindung geschieht von Hand, in einem eigenen Plugin oder im Theme. Ein Script-Tag im <head>, dann die PHP-Funktion der Dokumentation am Hook, der das Formular empfängt: Die Antwort ist allow oder deny.

Stand: .

Gibt es ein WordPress-Plugin?

Nein. Antisy bietet derzeit kein WordPress-Plugin an, und diese Anleitung kündigt keines an. Sie zeigt, was das Produkt heute liefert, ein Script-Tag und einen Serveraufruf, die Sie selbst in WordPress einbinden.

Die Prüffunktion ist die der Dokumentation. Die WordPress-eigenen Ausschnitte (wp_head, pre_comment_on_post, admin_post_*) verwenden Standard-Hooks; sie wurden zum Datum dieser Seite in keiner WordPress-Installation ausgeführt.

Was Sie brauchen

  • Eine Website, im Dashboard von Antisy (auf Französisch) angelegt, mit den Hostnamen Ihrer Seiten.
  • Der Site-Key (32 Zeichen): Er ist öffentlich und kommt in die Seite; das Verifizierungs-Secret (64 Zeichen) bleibt auf Ihrem Server und wird nur einmal angezeigt, bei seiner Erstellung.
  • Seiten, die über HTTPS ausgeliefert werden.
  • Zugriff auf ein eigenes Plugin oder auf das Theme (ein Child-Theme verhindert, dass die Änderungen bei einem Update verloren gehen) und auf die Datei wp-config.php.
  • PHP 8.0 oder neuer mit der Erweiterung cURL bei Ihrem Webhoster: Die Funktion der Dokumentation verwendet curl_init und den Typ mixed.

Siehe: Dokumentation: Schlüssel und Testumgebungen

Ist das heute verfügbar?

Der Zugang erfolgt über eine Warteliste. Die API und das Dashboard sind seit dem 27. Oktober 2026 in Betrieb, gehostet bei Infomaniak in Genf; noch ist kein Kunde in Produktion.

Die Beispiele dieser Anleitung folgen der Version 1 der API, wie die Dokumentation sie beschreibt. Um sie auszuprobieren, ohne ein echtes Formular zu schützen, beschreibt die Dokumentation Testschlüssel; ein Testschlüssel kommt nie in die Produktion.

Siehe: Dokumentation: Testschlüssel · Der Pilot · Der Warteliste beitreten

1. Die zwei Werte

In wp-config.php, ausserhalb des öffentlichen Stammverzeichnisses des Theme-Repositorys. Die Funktion der Dokumentation liest das Secret mit getenv('ANTISY_SECRET'). Bei einem Webhoster, der keine Umgebungsvariable anbietet, ändert sich eine einzige Zeile:

wp-config.php
<?php
// wp-config.php, oberhalb der Zeile « That's all, stop editing! ».
define('ANTISY_SITE_KEY', 'VOTRE_CLE_DE_SITE');                  // öffentlich: Er kommt in die Seite
define('ANTISY_SECRET', 'VOTRE_SECRET_DE_VERIFICATION');         // Secret: nie im Repository eines Themes

Eine Zeile der Funktion
// Ersetzen Sie in antisy.php diese Zeile der Funktion aus der Dokumentation:
'secret' => getenv('ANTISY_SECRET'),
// durch diese:
'secret' => ANTISY_SECRET,

2. Das Script-Tag in jeder Seite

Das Script-Tag wird vom Hook wp_head ausgegeben, mit dem Site-Key:

Plugin oder functions.php
<?php
// In einem eigenen Plugin oder in functions.php des Themes: das Script-Tag, im <head> jeder Seite.
add_action('wp_head', function () {
    if (!defined('ANTISY_SITE_KEY')) {
        return;
    }
    printf(
        '<script src="https://api.antisy.com/v1/i/l.js" data-site="%s" defer></script>' . "\n",
        esc_attr(ANTISY_SITE_KEY)
    );
});

// Die Funktion antisy_verdict() aus der Dokumentation, gespeichert in antisy.php neben dieser Datei.
require_once __DIR__ . '/antisy.php';

Das Token steht nicht im HTML der Seite: Das Script erzeugt es beim Absenden, im Browser. Eine Seite aus einem Seiten-Cache oder einem CDN funktioniert also wie jede andere. Wenn ein Optimierungs-Plugin Scripts verzögert, zusammenfasst oder umschreibt, prüfen Sie, dass das Script-Tag unversehrt ankommt: mit den gängigen Erweiterungen nicht geprüft.

3. Die Prüffunktion

Speichern Sie die PHP-Funktion der Dokumentation in antisy.php, neben der vorherigen Datei, ohne sie zu ändern ausser der Zeile des Secrets:

antisy.php
<?php
/**
 * Vérifie le jeton Antisy (mode simple). Rend le verdict : "allow" ou "deny".
 *
 * - jeton vide ou absent : envoyé tel quel, Antisy décide ; jeton non vide inutilisable : "deny", sans appel ;
 * - Antisy ne répond pas (réseau, délai, 5xx) : "allow" et on journalise (fail-open) ;
 * - 429 : ANTISY_ON_RATE_LIMIT ;
 * - tout autre statut que 200 (400, 401, 413, 415...) : erreur de VOTRE appel, journalisée,
 *   tentative non vérifiée : "deny". Jamais "allow".
 */
const ANTISY_ON_RATE_LIMIT = 'allow'; // 'deny' für ein sensibles Formular: Ein Angreifer kann einen 429 auslösen

function antisy_verdict(mixed $token): string
{
    if ($token === null) {
        $token = ''; // fehlendes Feld: wie leer behandelt
    }
    // Leer: unverändert gesendet, Antisy entscheidet (Erfassung an: deny; aus: die Engine entscheidet).
    // Nicht leer: 1 bis 2’048 druckbare ASCII-Zeichen; /D: « $ » duldet keinen abschliessenden Zeilenumbruch.
    if ($token !== '' && (!is_string($token) || !preg_match('/^[\x20-\x7e]{1,2048}$/D', $token))) {
        return 'deny'; // ein Formular-Array, ein zu langes oder präpariertes Token: was Antisy antworten würde
    }

    $ch = curl_init('https://api.antisy.com/v1/siteverify');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 3, // Sekunden; danach fail-open
        CURLOPT_FOLLOWLOCATION => false, // keiner Weiterleitung folgen (das ist der Standard, ausgeschrieben, damit sie niemand einschaltet): Eine 3xx ist ein Fehler IHRES Aufrufs
        CURLOPT_POSTFIELDS => http_build_query([
            'secret' => getenv('ANTISY_SECRET'), // siteverify-Secret; nie fest im Code und nie beim Client
            'response' => $token,
        ]),
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    // Einziger Fall, in dem durchgelassen wird: Antisy antwortet nicht.
    if ($body === false || $status >= 500) {
        error_log("Antisy injoignable, envoi laissé passer (fail-open): {$error} (HTTP {$status})");
        return 'allow';
    }
    if ($status === 429) {
        error_log('Antisy 429 (voie saturée): ' . ANTISY_ON_RATE_LIMIT);
        return ANTISY_ON_RATE_LIMIT;
    }
    if ($status !== 200) {
        error_log("Antisy HTTP {$status} : erreur de l'appel, à corriger ; tentative non vérifiée");
        return 'deny';
    }
    $result = json_decode($body, true);
    if (is_array($result) && is_bool($result['success'] ?? null)) {
        if ($result['success']) {
            return 'allow'; // die einzige Annahme
        }
        return 'deny'; // success false: Ablehnung (das Ergebnis ist « deny »)
    }
    error_log('Réponse Antisy illisible, tentative non vérifiée');
    return 'deny';
}

4. Die Kommentare schützen

Der Hook pre_comment_on_post läuft, bevor WordPress einen Kommentar verarbeitet:

Plugin oder functions.php
<?php
// Die Kommentare: Das Formular von WordPress sendet seine Felder an wp-comments-post.php, auf Ihrer Website.
// Dieser Hook läuft, bevor der Kommentar verarbeitet wird.
add_action('pre_comment_on_post', function () {
    if (antisy_verdict($_POST['antisy-token'] ?? '') !== 'allow') {
        wp_die('Envoi refusé.', 'Envoi refusé', ['response' => 403, 'back_link' => true]);
    }
});

WordPress sendet das Kommentarformular an wp-comments-post.php, auf Ihrer Website: Das ist ein POST an Ihre eigene Origin, den das Script abdeckt. wp_die antwortet mit 403 und bietet einen Link zurück an.

5. Ein selbst geschriebenes Kontaktformular schützen

Das Formular sendet an admin-post.php, das auf Ihrer Website liegt, mit einem versteckten Feld action, das den Hook wählt:

Vorlage des Themes
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
  <input type="hidden" name="action" value="antisy_contact">
  <label>Nom <input name="name" autocomplete="name"></label>
  <label>E-mail <input name="email" type="email" autocomplete="email"></label>
  <label>Message <textarea name="message"></textarea></label>
  <button>Envoyer</button>
</form>

Plugin oder functions.php
<?php
function antisy_contact_handler(): void
{
    if (antisy_verdict($_POST['antisy-token'] ?? '') !== 'allow') {
        wp_die('Envoi refusé.', 'Envoi refusé', ['response' => 403, 'back_link' => true]);
    }

    // … die Felder bereinigen, dann die Nachricht senden oder speichern (wp_mail, Beitrag, Datenbank …)

    wp_safe_redirect(home_url('/merci/'));
    exit;
}
add_action('admin_post_nopriv_antisy_contact', 'antisy_contact_handler'); // nicht angemeldeter Besucher
add_action('admin_post_antisy_contact', 'antisy_contact_handler');        // angemeldeter Besucher

Dieses Beispiel behandelt nur die Bot-Prüfung. Das Bereinigen der Felder, das Senden der Nachricht und die WordPress-eigenen Schutzmassnahmen bleiben bei Ihnen.

Und die Formular-Plugins?

Die Formular-Plugins (Kontakt, Offerte, Registrierung) haben jedes ihre eigene Art, eine Übermittlung zu empfangen und zu validieren. Diese Anleitung deckt sie nicht ab, ebenso wenig die Login-Seite von WordPress: nicht geprüft. Das Script deckt ein POST-Formular an Ihre Website auch dann ab, wenn die Seite es per fetch sendet, aber die Prüfung auf dem Server muss dort eingebunden werden, wo das Plugin die Übermittlung validiert, und das beschreibt diese Anleitung nicht.

Siehe: Dokumentation: welche Formulare das Script abdeckt

Was antwortet die Prüfung?

Die Antwort ist ein JSON-Objekt. success ist genau dann true, wenn verdict den Wert allow hat. Es gibt nur diese zwei Ausgänge, und die Antwort nennt nie den Grund: Auch die Ablehnung, die Sie dem Besucher zeigen, ist allgemein.

Ein Token ist 60 Sekunden gültig und lässt sich nur einmal prüfen. Ein zweiter Aufruf mit demselben Token wird abgelehnt.

Antwort von POST /v1/siteverify (HTTP 200)
{
  "success": true,
  "verdict": "allow",
  "flags": [],
  "error-codes": [],
  "challenge_ts": "2026-09-24T10:00:00Z",
  "hostname": "shop.example",
  "action": "contact",
  "event_id": "evt_01J7X4M2Q9K8ZP3R5T6V7W8Y9A"
}

Siehe: Dokumentation: Anfrage, Antwort und Fehlercodes

Und wenn Antisy nicht antwortet?

Die Funktion lässt die Übermittlung in einem einzigen Fall durch: Antisy antwortet nicht (Netz unterbrochen, Zeitlimit von 3 Sekunden überschritten, Fehler 5xx). Ein Ausfall von Antisy darf Ihr Formular nicht schliessen.

Jeder andere HTTP-Fehler (400, 401, 413, 415) kommt von Ihrem Aufruf: Die Funktion lehnt die Übermittlung ab und protokolliert sie, nie ein Freipass. Ein 429 ist eine Entscheidung, die bei Ihnen liegt: Die Konstante ANTISY_ON_RATE_LIMIT steht standardmässig auf allow; setzen Sie deny für ein sensibles Formular.

Siehe: Dokumentation: Anfrage, Antwort und Fehlercodes

Was passiert, wenn das Script blockiert ist?

Eine CSP-Richtlinie, die das Script verweigert, ein Werbeblocker, eine Seite über HTTP oder ein Besucher ohne JavaScript verhindern, dass das Script läuft. Das Formular wird dann trotzdem gesendet, ohne das Feld antisy-token: Lesen Sie es mit einem leeren Standardwert.

Was folgt, hängt von der Einstellung « Collecte du navigateur » (Erfassung im Browser) der Website ab. Ist die Erfassung an, kommt eine Übermittlung ohne Token nicht durch; ist sie aus, wird das fehlende Token nicht angelastet. Eine neue Website beginnt mit ausgeschalteter Erfassung.

Siehe: Dokumentation: wenn das Script nicht läuft

Was eine Bot-Prüfung nicht ersetzt

Keine Bot-Prüfung ist perfekt, und Antisy nennt keine Erkennungsrate. Sie kommt zu den anderen Abwehrmassnahmen eines Formulars hinzu, etwa der Begrenzung der Anzahl Übermittlungen; sie ersetzt sie nicht.

Häufige Fragen

Gibt es ein Antisy-Plugin für WordPress?

Nein. Antisy bietet derzeit kein WordPress-Plugin an. Die Einbindung geschieht von Hand: ein Script-Tag im <head> des Themes oder eines eigenen Plugins, und die PHP-Funktion der Dokumentation am Hook, der das Formular empfängt.

Wohin mit dem Secret von Antisy in WordPress?

In eine Umgebungsvariable des Servers, wenn Ihr Webhoster eine anbietet, sonst in wp-config.php, zusammen mit dem Site-Key. Das Secret kommt nie in das Repository eines Themes, nie in die Seite und nie in ein Protokoll.

Stört ein Seiten-Cache oder ein CDN das Antisy-Token?

Das Token steht nicht im HTML: Das Script erzeugt es beim Absenden, im Browser jedes Besuchers. Eine Seite aus dem Cache funktioniert also wie jede andere. Das Risiko liegt woanders: Ein Optimierungs-Plugin, das Scripts umschreibt, kann das Script-Tag beschädigen, und diese Anleitung hat das mit den gängigen Erweiterungen nicht geprüft.

Siehe auch: PHP-Formular vor Bots schützen, ohne Rätsel · Next.js-Formular vor Bots schützen, ohne Rätsel · Alle Anleitungen · Dokumentation: Schritt-für-Schritt-Anleitung