XHTMLforum

XHTMLforum (http://xhtmlforum.de/index.php)
-   Serveradministration und serverseitige Scripte (http://xhtmlforum.de/forumdisplay.php?f=80)
-   -   Bitte austesten: Formular-Spamschutz (http://xhtmlforum.de/showthread.php?t=51007)

fox 20.03.2008 21:07

Bitte austesten: Formular-Spamschutz
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habs ja schon ein paar mal angesprochen - die Idee vom barrierefreien, benutzerfreundlichen und spamsicheren Kontaktformular.

Nun habe ich den PHP-Code noch ein bisschen weiterentwickelt und eine Klasse daraus gebastelt. Meine bitte an euch wäre, die Klasse mal komplett auszutesten, hinsichtlich funktionalität, etc.

Das Einbinden ist zwar weiterhin ein bisschen komplex, aber doch leichter als bisher.

Das Skript (welches unter der LGPL steht) findet sich im Anhang, hier ist ein kommentiertes Beispiel dazu. Bitte sagt Bescheid, wenn ihr Fehler findet oder Verbesserungswünsche habt :)

PHP-Code:

$form_sent false;

// Eine neue Instanz der Klasse wird erzeugt
$form = new SecureForm();

// Für jedes Formfeld wird eine zufällige (CSS-)ID erzeugt und in den Variablen gespeichert
$id_name $form->getID('name');
$id_email $form->getID('email');
$id_nachricht $form->getID('nachricht');

// Der Submit-Button muss nicht zwangsweise "anonymisiert" werden
$id_submit $form->getID('submit');


// Die CSS-Datei wurde vom Browser angefordert und wird abgeschickt
if (isset ($_GET['getCSS'])) {
    
header ("Content-Type: text/css");
    
$form->generateCSS();
    exit;
}

// Es wird nun geprüft, ob der Submit-Knopf gedrückt und das Formular abgesendet wird.
// Die Formularfelder sind mit den verschiedenen IDs als Namen gespeichert.
if (!empty ($_POST[$id_submit])) {
    
$form_sent true;
    
    
// Zuerst überprüfen wir, ob alle gewünschten Felder ausgefüllt sind
    
if (!empty ($_POST[$id_name]) && !empty ($_POST[$id_email]) && !empty ($_POST[$id_nachricht])) {
        
        
// Danach wird geprüft, ob das versteckte Feld ausgefüllt wurde.
        // Sollte das der Fall sein haben wir es höchstwahrscheinlich mit einem Spambot zu tun
        // Hier könnten auch weitere Aktionen unternommen werden, z.B. loggen und/oder sperren der IP des Bots, o.ä.
        
if (!empty ($_POST[$form->getSecretID()])) {
            
session_destroy ();
            echo 
'Spambot erkannt.';
            exit;
        }
        
        
// Nun können wir die E-Mail versenden
        
$name $_POST[$id_name];
        
$email $_POST[$id_email];
        
$nachricht $_POST[$id_nachricht];
        
        
// E-Mail verschicken... 
        
        
session_destroy ();
        exit;
    }
    
    
// Falls nicht alle Felder ausgefüllt sind sollte die Session-ID sowie die geheimen IDs erneuert werden,
    // um mögliche Brut-Force-Angriffe von Bots aus dem Weg zu gehen.
    // WICHTIG: Vor dem erneuern dürfen die Header noch nicht gesendet werden!
    
$form->regenerateIDs();
}

/* Nun wird das Formular erzeugt:
Eventuell wird es auch in Templates eingebunden o.ä.
Vorher sollten normalerweise der HTML-Kopf, etc. kommen
Wichtig ist, dass die Session-ID übergeben wird!
Alternativ kann diese auch mit einem versteckten Feld und POST übergeben werden,
PHP erkennt diese automatisch.
Außerdem dürfen die beiden Stylesheets nicht fehlen!

Das erste Stylesheet ist die Vorgabe für die normalen Felder.
Da diese Angabe *vor* den anderen kommt, gilt diese.
Bei den versteckten Feldern wird zusätzlich ein !important hingehängt, damit werden die Felder unsicht- und -hörbar.*/

echo '<style type="text/css">
.form input, .form textarea {
    position: static !important;
    display: block !important;
    speak: normal !important;
}
</style>
<link rel="stylesheet" type="text/css" href="secureForm.php?getCSS&' 
SID '" media="all" />

<form action="secureForm.php?' 
SID '" method="POST" class="form">';

// Nun werden die einzelnen Eingabefelder ausgegeben.
// Dabei wird gleich überprüft, ob das Formular bereits abgesendet wurde und ob Felder fehlen.
echo '<label>Dein Name' . ((($form_sent && empty ($_POST[$id_name]))) ? ' (fehlt)' '') . ':</label> <input type="text" id="' $id_name '" name="' $id_name '" value ="' . ((!empty ($_POST[$id_name])) ? htmlspecialchars ($_POST[$id_name]) : '') . '" /><br />
<label>Deine E-Mail-Adresse' 
. ((($form_sent && empty ($_POST[$id_mail]))) ? ' (fehlt)' '') . ':</label> <input type="text" id="' $id_email '" name="'  .$id_email '" value="' . ((!empty ($_POST[$id_email])) ? htmlspecialchars ($_POST[$id_email]) : '') . '" /><br />
<label>Deine Nachricht' 
. ((($form_sent && empty ($_POST[$id_nachricht]))) ? ' (fehlt)' '') . ':</label><br />
<textarea name="' 
$id_nachricht '" id="' $id_nachricht '">' . ((!empty ($_POST[$id_nachricht])) ? htmlspecialchars ($_POST[$id_nachricht]) : '') . '</textarea>
<input type="text" name="' 
$form->getSecretID() . '" id="' $form->getSecretID() . '" value="" />' // Auch das versteckte Feld bekommt seinen Platz
'<input type="submit" name="' $id_submit '" id="' $id_submit '" value="Formular absenden" />';

// Fertig. :)
// Man könnte das versteckte Feld noch an zufälligen Positionen erscheinen lassen, um es den Spambots nicht zu leicht zu machen. 

Ein bisschen viel Aufwand - aber bis jetzt noch sicher ;)

Ich hoffe, dass das ganze halbwegs verständlich war und ich damit ein paar Formulare mehr Spamsicher und Benutzerfreundlich machen konnte ;)

paracelsus 20.03.2008 22:29

Also Gratuliere!

Soweit ich das beurteilen kann, werkelt das prima!
Das einbinden fällt gar nicht schwer.

Frage: die Style Definitionen tragen important, warum?

Darf ich das Teil in meinem CMS verwenden?
Gerne auch mit Hersteller Namen im Quelltext!

genial das script!

Lemmi 21.03.2008 02:30

Ich finde die Idee, dass der Bot nicht in der Lage ist, Felder nach Wichtigkeit zu unterscheiden, wirklich gut. Und wie ich bereits sagte, hat mich diese Idee auch bei meinem Kontaktformular geholfen.

Die ganze Sache ist mir insgesamt, wie du ja selber schon gesagt hast, etwas zu unkomfortabel. Ich halte es halt für einfacherer und noch barrierefreundlicher, wenn man sich ein paar Felder überlegt, die man nicht mit CSS verstecken muss. Aber gut, dass ist dann vielleicht auch ein Stück weit Geschmackssache. ;)

paracelsus 21.03.2008 10:16

Ein Feld das nicht versteckt ist, wird garantiert von dem einem oder andern User ausgefüllt.
Und dann?

Lemmi 21.03.2008 12:15

Dann handelte es sich um die Postleitzahl oder Hausnummer und die dazugehörige Straße, in der mein Kontaktmann wohnt.
Und diese Eingaben lassen sich von der Form her sehr grob kontrollieren.
Die Hausnummer und Straße sind von einem Leerzeichen getrennt, die Hausnummer ist logisch eine Zahl.

Beispiel: VIPixel - Webdesignbüro

paracelsus 21.03.2008 13:26

Ich verstehe ietzt was Du meinst.
Halte aber die Methode/Idee von fox für einen Tick sicherer.

Mal sehen wie das Formular tut, wenn man es in ein bestehendes Design-Set einbaut. Dazu komme ich erst in ein paar Tagen.

Gruß

fox 21.03.2008 14:43

Hallo,

danke erstmal fürs testen.

Zitat:

Zitat von paracelsus (Beitrag 377430)
Darf ich das Teil in meinem CMS verwenden?
Gerne auch mit Hersteller Namen im Quelltext!

Natürlich! Dafür steht das Skript ja unter der LGPL-Lizenz. Wenn du meinen Namen erwähnst würde ich mich sehr freuen. :)

Zitat:

Zitat von paracelsus (Beitrag 377430)
Frage: die Style Definitionen tragen important, warum?

Das ist der Trick an der Sache:
Durch das !important werden die späteren Style-Definitionen, die vom Skript generiert werden, außer Kraft gesetzt.

Wir haben also dann zwei Regeln:

1. Das !important vor den Skript-Definitionen
2. Die Skript-Definitionen mit oder ohne !important.

Wenn jetzt im Skript selbst ein !important steht, wird diese Regel verwendet, andernfalls die Regel aus der ersten Definition. Somit steht zwar bei dem Skript-CSS bei allen Feldern display:none, etc. - aber nur bei den IDs mit !important hinten dran gelten diese Regeln auch. D.h. die Felder, die angezeigt werden sollen bekommen kein !important. :)

Zitat:

Die ganze Sache ist mir insgesamt, wie du ja selber schon gesagt hast, etwas zu unkomfortabel. Ich halte es halt für einfacherer und noch barrierefreundlicher, wenn man sich ein paar Felder überlegt, die man nicht mit CSS verstecken muss. Aber gut, dass ist dann vielleicht auch ein Stück weit Geschmackssache.
Dass das ganze einen gewissen Aufwand erfordert ist mir klar, das lässt sich wohl auch nicht so leicht ändern.
Aber deine Methode hat einen gewissen Nachteil: Die Bots können darauf angepasst werden, da die Felder und Feldnamen immer gleich sind. Wie hoch die Wahrscheinlichkeit ist, dass das ein Spammer sowas wirklich macht, bleibt abzuwarten, müsste man eventuell austesten. :roll:

Fakt ist jedenfalls, dass beide Methoden bis dato relativ sicher sind, wenn ich das mal behaupten darf. :)

Lemmi 21.03.2008 15:48

Zitat:

Zitat von fox (Beitrag 377513)
Fakt ist jedenfalls, dass beide Methoden bis dato relativ sicher sind, wenn ich das mal behaupten darf. :)

Das hoffe ich doch! ;) :)

SWT 21.03.2008 15:58

Hallo Fox,

erst einmal vielen, vielen Dank für Dein Skript. Die Idee mit dem getarnten Eingabefeld ist super.
Leider funktioniert bei mir aber genau diese Tarnung nicht. :shock:
Ich habe einmal Dein Test-Skript wie es in der zip-Datei von heute Mittag zu finden ist hochgeladen. Nachdem ich einen kleinen Fehler korrigiert hatte (das Formular verweist auf secureForm.php, müßte aber auf secureForm_example.php verweisen) funktioniert die prinzipielle SPAM-Bot-Erkennung. Nur wird - wie gesagt - das getarnte Eingabefeld nicht getarnt.

Hier der Link
http://web199.michelle.webhoster.ag/...rm_example.php

Über einen Tip würde ich mich sehr freuen.

Danke + Gruß
SWT

paracelsus 21.03.2008 16:36

Kann ich gleich machen:
Du hast zwar den Formverweis korrigiert, aber den CSS Verweis nicht!

<link rel="stylesheet" type="text/css" href="secureForm_example.php?getCSS&PHPSESSID=0g6o0lmrpckrrd7n49fq0geh12" media="all" />
Wenn Du schon dabei n´bist, wirf auch das "&" im URL raus und ersetze es durch "&amp;".

Gruß


Alle Zeitangaben in WEZ +2. Es ist jetzt 10:04 Uhr.

Powered by vBulletin® Version 3.8.11 (Deutsch)
Copyright ©2000 - 2024, vBulletin Solutions, Inc.

© Dirk H. 2003 - 2023