dedlfix: Verständnisfrage Formularvalidierung

Beitrag lesen

Tach!

Ich habe dazu folgenden Beispielcode erstellt und lasse ihn in 3 unterschiedlichen weisen Ausgeben. Das Phänomen was ich mir nicht erklären kann ist, dass das Zeichen < nicht verarbeitet wird, alle anderen Zeichen werden unter 1 ganz normal ausgegeben.

Du verwendest FILTER_SANITIZE_STRING. Wenn du dazu im Handbuch nachschlägst, was das bewirkt, siehst du: Strip tags, optionally strip or encode special characters. Die Eingabe wird also verändert.

Aber ist das der richtige Weg, Dinge aus Eingaben zu entfernen oder umzuschreiben? Was ist denn das eigentliche Problem? Nun, Eingabedaten an sich sind harmlos. Probleme entstehen erst dann, wenn man die Daten (und dabei spielt es keine Rolle, ob sie aus einer Eingabe stammen oder sonstwoher) in Richtung eines anderen Systems ausgibt und dieses System Teilen der Daten eine Sonderrolle jenseits von simplem Text zuweist. Zum Beispiel ist das System HTML ein Mischmasch aus anzuzeigendem Text und Steuerinformationen, um bestimmte Abschnitte in diesem Text besonders auszeichnen zu können: als Überschrift, Absatz, Tabelle, Liste, Formular und so weiter. Diese Steuerinformationen werden nun mit denselben Zeichen dargestellt, wie sie auch im Text vorkommen können, und dabei ist es wichtig, korrekt unterscheiden zu können, was nun eigentlich gemeint ist. Ist ein < nun der Beginn eines HTML-Tags oder ist es einfach nur ein Kleiner-Als-Zeichen? In HTML löst man das Dilemma für das < so, dass es als Tag-Bestandteil direkt geschrieben wird, als Text ohne weitere Bedeutung jedoch maskiert werden muss, und als &lt; zu notieren ist (alternative Schreibweisen existieren auch).

Kann mir jemand sagen, woran das liegt (also warum der Filter so agiert) und was man für eine Validierung von Text besser nutzen kann/sollte unter Berücksichtigung aller Sonderzeichen?

Ein Eingangsdatenfilter versucht nun, diese Eingabedaten bereits so zu gestalten, dass keine Unklarheiten entstehen. Aber kann er das denn überhaupt? Nein, nicht vollständig. Je komplexer ein System wird, desto weniger weiß die Eingabe, wo am Ende die Daten überall landen werden. Und neben HTML gibt es noch eine Menge anderer Systeme, die ihre eigenen Definitionen haben, was ein Sonderzeichen ist und was nicht, zuzüglich wie Maskierungen zu notieren sind. Zudem müssen diese Regeln für alle Daten beachtet werdenm, nicht nur die, die aus einer Nutzereingabe stammen. Die Eingabefilter sind also meistens ein nicht besonders brauchbares Instrument, den Problemen an den unterschiedlichen Ausgängen zu begegnen. Das Dilemma fällt bereits dann auf, wenn die Daten zwei Wege gehen sollen, einer könnte die SQL-Datenbank sein, der andere die HTML-Ausgabe. Man kann die Eingabe nicht so sanieren, dass alle Zeichen erhalten bleiben und gleichzeitig für alle Ausgabesysteme korrekt maskiert sind. Deshalb sind solche Eingabefilter, wenn überhaupt, nur bedingt brauchbar. Der bessere Weg ist, die Daten erst direkt vor der Übergabe in ein weiteres System zu behandeln und zwar nach den speziellen Regeln dieses Systems. Das nennt sich Beachtung des Konextwechsels und ist im Wiki ausführlich beschrieben.

Konkrete Anmerkungen zum Code:

echo "<form accept-charset=\"utf-8\" action=\"\" method=\"post\">";
echo "<input type=\"text\" id=\"value\" name=\"value\" value=\"\" autocomplete=\"off\">";
echo "<input type=\"submit\">";
echo "</form>";

Einen Block aufzuteilen und als einzelne echo-Anweisungen auszugeben ist recht umständlich, besonders wenn keine Variablenersetzungen oder andere Änderungen drin vorkommen. PHP verlassen ?>, das HTML direkt notieren und für PHP-Code wieder zu PHP wechseln, ist einfacher zu notieren und auch zu lesen. Alternativ gibt es auch die Heredoc- und Nowdoc-Syntax von Strings.

$POST_value = ""; if(isset($_POST['value'])) { $POST_value = filter_input(INPUT_POST, 'value', FILTER_SANITIZE_STRING); }

Der Filter klaut bereits das < und gegebenenfalls nachfolgende Zeichen. Das htmlentities() in nachfolgenden Code hat nun nichts mehr zu tun. Wenn der Filter weggelassen wird, sorgt htmlentities() dafür, dass Sonderzeichen richtig für die HTML-Ausgabe maskiert werden.

echo "1".$POST_value."<br><br>";
echo "2".htmlentities($POST_value)."<br><br>";
echo "3".$_POST['value'];

Apropos htmlentities(), diese Funktion macht viel zu viel. Sie maskiert nicht nur die für HTML notwendigen Zeichen, sondern auch Dinge wie Umlaute, was aber nicht erforderlich ist, wenn man mit dem Thema Zeichenkodierung korrekt umgeht. htmlspecialchars() hingegen kümmert sich lediglich um die notwendigen Zeichen. Es ist besser, diese Funktion zu verwenden, damit die Ausgabe nicht durch unnötige Maskierungen angereichert wird.

dedlfix.