Es ist schon immer ein guter Ansatz gewesen zuerst einmal alle Daten (ob diese nun von einem Benutzer eingegeben werden oder nicht) als ungültig zu erklären. Gültig werden sie erst dann, wenn man bestätigen kann, dass sie einen erlaubten Wert besitzen.
Beispielfragen sind:
- Hat der Benutzer eine gültige E-Mail Adresse eingegeben?
- Hat der Benutzer eine gültige Ganzzahl eingegeben?
- Und so weiter.
Dabei gibt es zwei Haupttypen der Filterung:
- Validierung
Sie wird benutzt um zu prüfen, ob die vorliegenden Daten gewisse Bedingungen erfüllen. Ob z.B. eine E-Mail-Adresse ein @-Zeichen enthält. Die ursprünglichen Daten werden dabei jedoch nicht verändert. - Säuberung
Unter Säuberung versteht man das Verändern der Daten. Und zwar so, dass sie am Ende nur die Daten enthalten damit die Bedingungen für die Validierung erfüllt sind.
Warum Validieren und Säubern wichtig ist
Nehmen Sie ein einfaches Formularfeld dessen Eingabe weder geprüft noch gesäubert wird. Das bedeutet: Weder die Ein- noch die Ausgabe werden auf ihre Gültigkeit geprüft.
<form>
<input type="text" placeholder="Ein Text" name="eingabe" value="<?php echo isset( $_GET['eingabe'] ) ? $_GET['eingabe'] : ''; ?>" />
<input type="submit" />
</form>
So lange ein Benutzer nur reinen Text eingibt ist alles in Ordnung. Wenn er jedoch anfängt, HTML Code einzugeben, wir es problematisch.
Noch dazu, wenn keine Überprüfung stattfindet und das Script sich selbst ausführt. Nach dem Absenden wird nämlich ein zweites Formularfeld zur Bildschirmausgabe hinzugefügt welches ursprünglich nicht vorhanden war:
Ich gebe zu: dieses Beispiel ist nicht sonderlich gefährlich. Wenn ein Benutzer jedoch schädlichen Code übertragen will, wird er hier alles mögliche ausprobieren. So kam es auch schon vor, dass durch solche ungeschützte Formulare ganze Datenbanken ausgelesen werden konnten. Es wird also ein Code übertragen der, einmal ausgeführt, unter umständen schädlich sein kann. Im Fachjargon nennt man das Cross-Site-Scripting oder kurz: XSS.
Daten richtig validieren
Nehmen wir einmal an Sie programmieren ein Plugin welches mit Hilfe eins Formulars folgende Daten eines Benutzer abfragt:
- das Alter und
- das Geschlecht.
Der Ausgabe-Code des Formulars sieht dann ungefähr so aus:
<form action="abgesendet.php" method="post">
<p>
Ihr Alter:<br />
<input type="text" name="age" value="" />
</p>
<p>
Ihr Geschlecht:<br />
<input type="radio" name="gender" value="m" />
<input type="radio" name="gender" value="w" />
</p>
<input type="submit" value="Senden" />
</form>
Beim Speichern der Daten müssen diese richtig validiert werden. Und zwar in etwa so:
<?php
$age = isset( $_POST['age'] ) ? abs( $_POST['age'] ) : 0;
$gender = '';
if ( isset( $_POST['gender'] ) && in_array( $_POST['gender'], array( 'm', 'w' ) ) ) {
$gender = $_POST['gender'];
}
speichere( $age, $gender );
?>
Wie Sie sehen wird versucht, die Daten so zu umschreiben, dass sie immer einen gültigen Wert erhalten.
- Mittels der PHP-Funktion
abs()
wird das Alter immer in eine positive Zahl umgewandelt. Auch dann, wenn der Benutzer einen Text (wie z.B. „XYZ“) eingibt (die Funktion liefert dann den Wert „0“ zurück). - Das Geschlecht wird einfach ignoriert (bzw. erhält einen leeren Wert) wenn es keinen gültigen Wert („m“ oder „w“) enthält.
Daten filtern
Die einmal abgeschickten Daten müssen verarbeitet und anschließend validiert werden. Wenn der Validierungsprozess abgeschlossen ist können Sie entscheiden, was mit den Daten passieren soll. Sie haben demnach zwei Möglichkeiten:
- Sie können die Daten komplett verwerfen. Diese gehen dadurch verloren.
- Sie können die Daten filtern (bzw. säubern) um unerwünschte Zeichen oder unerwünschten Code zu entfernen.
Wenn möglich sollten Sie sich für das Filtern entscheiden. Das bedeutet zwar einen Mehraufwand sorgt aber für mehr Benutzerfreundlichkeit. Nehmen Sie an, ein Benutzer hat einen längeren Text eingegeben und schickt diesen ab. Nun befinden sich darin einige Zeichen, die sich nicht erlaubt haben und verwerfen den Text. Der Benutzer müsste nun alles erneut eingeben. Das ist nervig, denn er speichert mit großer Wahrscheinlichkeit seine Daten nicht parallel an anderer Stelle ab.
Besser wäre es gewesen, wenn nur die ungültigen Zeichen gefiltert worden wären.
Aber natürlich können Sie nicht alle Daten passend filtern. Wenn (wie im Beispiel von oben) das Alter abgefragt wird, der Benutzer aber einen Text wie „XYZ“ eingibt, können Sie nicht auf das Alter schließen. Hier müssen Sie die Daten wohl oder übel verwerfen.
Nutzung der Settings-API zum Filtern
In Kapitel 4.3.6. Eine Einstellung registrieren haben sie gelernt, dass beim Registrieren einer Einstellung (bzw. eines Feldes) auch der Parameter $sanitize_callback
mit angegeben werden kann. Damit können Sie eine Funktion angeben, die vor dem Speichern der Einstellung auf den Wert angewendet wird.
<?php
register_setting(
// Gruppe
'mm_settings_group',
// Name
'mm_settings_section_1_field_1',
// Callback Funktion
'sanitize_text_field'
);
?>
Filterbeispiele für die Eingabe
Filterbeispiele für die Ausgabe
Auch Ausgaben sollten, wenn möglich, immer gefiltert werden. Das stellt sicher, dass die Ausgabe im Browser auch korrekt dargestellt wird.
Viele WordPress Filter-Funktionen können zur Ein- bwz. Ausgabefilterung gleichermaßen benutzt werden. So haben Sie im Kapitel 5.4.5.9. weiter oben schon gelernt, dass esc_url()
automatisch immer auch Entitäten umwandelt. Gibt man jedoch als dritten Parameter als Kontext z.B. db
an, passiert dies nicht. Damit lässt sich die Funktion dazu nutzen, URLs zu filtern und dann in die Datenbank zu speichern. Vereinfacht lässt sich natürlich auch die Funktion esc_url_raw()
direkt nutzen.
Hier einige Beispielfunktionen, die Sie bereits kennen gelernt haben: