öffentlich
Redaktion Druckversion

PHP lernen (3): Interaktive Webseiten gestalten

Querystrings

Ganz kurz haben Sie oben schon gesehen, wie Daten an einen URI gehängt werden. Dabei hängen Sie an den URI mittels Fragezeichen einen sogenannten Querystring an:

http://www.domain.de/beispiel.php?variable=wert

Mit diesem Link wird die Datei beispiel.php aufgerufen. In dieser Datei steht nun die Variable mit Namen variable und dem Wert wert zur Verfügung. Sie sprechen die Variable über das Array $_REQUEST oder $_GET an. Schreiben Sie folgenden Code in eine Datei, die Sie als beispiel.php abspeichern:

<?php
print $_GET["variable"];    // Ausgabe: wert
?>

Wenn Sie diese Datei über den oben angegebenen Link mit Querystring aufrufen, tut die Datei nichts weiter als den Wert des Querystrings ausgeben. Wir wollen ein wenig mit Querystrings experimentieren. Schreiben Sie sich dazu ein Skript, das im Body-Tag zuerst das Array $_GET komplett ausgibt und darunter schreiben Sie einen Link:

<?
print '<pre>';
print_r($_GET);
print '</pre>'; 
?>

<a href="php1_w3_02.php?variable=wert">Dies ist ein Link</a>

Speichern Sie das Skript unter dem Namen php1_w3_02.php. Wenn Sie das Skript zum ersten Mal aufrufen, wird $_GET leer sein. Klicken Sie nun auf den Link, wird das gleiche Skript aufgerufen, im Array $_GET steht aber die Variable $_GET['variable'].

Sie können auch mehrere Variablen in einen Querystring schreiben:

<a href="beispiel.php?variable1=wert1&variable2=wert2">mehrere Variablen</a>

Übertragen werden sowohl Zeichenketten also auch Zahlen. Als Datentypen erkennt PHP automatisch eine Zeichenkette.

Übertragung von Arrays im Querystring

Arrays können Sie so nicht übertragen. Wenn Sie Arrays per Querystring übertragen möchten, hängen Sie jedes Element des Array einzeln an. Verwenden Sie für den Variablennamen die eckigen Klammern, dann erkennt PHP bei der Entgegennahme gleich wieder das Array:

<a href="beispiel.php?variable[]=wert1&variable[]=wert2">Array</a>

Diese Variablen werden von PHP als Array entgegen genommen. $_GET["variable"] ist nun ein Array, keine skalare Variable mehr. Verwenden Sie zum Beispiel einen Index, um die einzelnen Elemente auszugeben:

<?php
print $_GET["variable"][0];    // Ausgabe: wert1
print '<br>';
print $_GET["variable"][1];    // Ausgabe: wert2
?>

URL Kodierung

Wenn Sie Zeichenketten über die URL weiterreichen, sollten Sie grundsätzlich in Erwägung ziehen, diese zu kodieren. Wenn Sie zum Beispiel Benutzereingaben über die URL transportieren, dann können Sonderzeichen in der Zeichenkette stehen. Solche Sonderzeichen müssen für die URL kodiert werden. Die meisten Browser machen das selbstständig, Sie können sich aber nicht darauf verlassen, wie die Zeichenketten kodiert werden und ob sie wieder korrekt dekodiert werden. Machen Sie es also im Zweifelsfall selbst und gezielt mit den PHP-Funktionen rawurlencode() und rawurldecode(). Setzen Sie in den Wert ein Leerzeichen, um die Kodierung sichtbar zu machen:

<a href="php1_w3_02.php?kodiert=<?=rawurlencode ('wert 1');?>">
   kodiert</a>

Wenn Sie auf diesen Link klicken, sehen Sie in der Adresszeile des Browsers einen Link in dieser Art:

http://localhost/Workshop/Woche3/php1_w3_02.php?kodiert=wert%201

Das Leerzeichen wurde durch %20 ersetzt. In der Ausgabe wird Ihr Browser wahrscheinlich automatisch das %20 wieder dekodieren. Im Zweifel dekodieren Sie die Zeichenkette selbst mit rawurldecode():

print rawurldecode($_GET['kodiert']);

Wenn Sie dagegen genau wissen, was in den Werten des Querystrings steht, weil Sie ihn selbst generieren, brauchen Sie die Kodierung gegebenenfalls nicht. Sobald jedoch Leer- oder Sonderzeichen im Querystring stehen können, sollten Sie die Zeichenketten kodieren.

Keine sensiblen Daten im Querystring!

Da der Querystring für jeden Benutzer offen zugänglich ist, sollten hier keine sensiblen Daten weitergereicht werden. Passwörter gehören niemals in den Querystring! Der Rechner des Benutzers könnte von Dritten eingesehen werden, der über den Verlauf im Webbrowser die besuchten Webseiten samt Querystring einsehen kann. Steht der Rechner in einem Netzwerk, kann der Netzwerkverkehr von Unbefugten abgehört werden. Dabei sind URIs mit angehängtem Querystring ebenfalls sichtbar.

Beispiel: Hintergrundfarbe

Zur Veranschaulichung sehen Sie hier ein einfacheres Beispiel, das eine solche Variable verwendet, um die Anzeige der Hintergrundfarbe zu steuern. Verwenden Sie die Variable dabei direkt, kann ihnen etwas untergeschoben werden. Schreiben Sie in eine Datei php1_w3_03.php folgenden Code:

<html>
<head></head>
<body bgcolor="<?=$_GET["bg"];?>">
<a href="php1_w3_03.php?bg=red">rot</a><br>
<a href="php1_w3_03.php?bg=green">grün</a>
</body>
</html>

Rufen Sie diese Datei nun zum Beispiel so auf: http://localhost/Workshop/php1_w3_03.php. Klicken Sie auf einen der Links. Sie sehen den Querystring in der Adresszeile offen vor sich liegen und können ihn als Benutzer natürlich manipulieren. Sie wollen einen gelben Hintergrund? Ändern Sie einfach die Adresszeile:

http://localhost/Workshop/php1_w3_03.php?bg=yellow

Das ist nicht weiter schlimm, weil der Benutzer hier nur die eigene Anzeige manipuliert. Einfluss auf die Anzeige der Webseite für Dritte hat er hiermit nicht. Dennoch wollen wir nur bestimmte Werte zulassen.

Die Schließung dieser Sicherheitslücke erfolgt durch Prüfung der Variablen auf ihren erlaubten Wert. Hier könnte man prüfen, ob die Variable entweder den Wert red oder den Wert green hat, und nur dann die Übergabe in das HTML-Attribut bgcolor erlauben:

<?
if ($_GET["bg"] == "red" || $_GET["bg"] == "green")
{
    $bg = $_GET["bg"];
}
else
{
    $bg = "white";
}
?>
<body bgcolor="<?=$bg;?>">

Hat die Variable einen anderen Wert, wird die Hintergrundfarbe auf weiß gesetzt. Wenn Sie mehr als zwei mögliche Werte überprüfen, wird das schnell unkomfortabel. Arbeiten Sie dann mit einem Array, das die erlaubten Werte enthält. Die folgende Variante ist auch leichter erweiterbar.

<?
$arrErlaubteWerte = array("red", "green");

if (in_array($_GET["bg"], $arrErlaubteWerte))
{
    $bg = $_GET["bg"];
}
else
{
    $bg = "white";
}
?>
<body bgcolor="<?=$bg;?>">

Die Funktion in_array() prüft, ob ein bestimmter Wert in einem Array vorhanden ist. Wenn nun der Querystring unerlaubt manipuliert wird, wird die Hintergrundfarbe einfach auf weiß gestellt. Wollen Sie weitere Farben erlauben, ergänzen Sie diese einfach in Ihrem Array.

Sie vergeben hier für $bg entweder den einen oder einen anderen Wert. Das können Sie mit einer if-else-Anweisung schreiben oder in der syntaktischen Kurzform:

$bg = (in_array($_GET["bg"], $arrErlaubteWerte)) ? $_GET["bg"] : "white";

Die Syntax folgt dem Muster:

(Ausdruck) ? true : false;
// (wenn das wahr) ? tue dies : sonst tue das;
// bzw.
$variable = (Ausdruck) ? true : false;
// $variable = (wenn das wahr) ? dieser Wert : sonst anderer Wert;

Diese Schreibweise bietet sich immer dann an, wenn eine if-else-Anweisung mit je einer Anweisung benötigt wird.

Wie bereits erwähnt, wäre in diesem Beispiel eine Manipulation des Querystrings nicht weiter schlimm, weil sie keinen Einfluss auf die Anzeige der Webseite für Dritte hätte. Wie gefährlich solche Manipulationen im Zweifel sein können, zeigt das nächste theoretische Beispiel. Greifen wir ein wenig auf eine Datenbankanwendung vor.

Beispiel: ID für Datenbankabfrage

Wenn Sie einen bestimmten Datensatz aus der Datenbank anzeigen wollen, übergeben Sie in einer Übersicht mit dem Link häufig die ID dieses Datensatzes. Der Redakteur oder Benutzer kann dann einen bestimmten Datensatz auswählen und anschließend bearbeiten oder löschen. Eine solche Liste sieht im Endergebnis in etwa so aus:

<a href="news.php?id=1">erste News</a><br>
<a href="news.php?id=2">zweite News</a><br>

In der Adresszeile des Browsers steht nach Klick auf einen der Links:

http://localhost/news.php?id=1

Aus dieser ID generiert das Skript in der Datei news.php eine Datenbankabfrage, die den betreffenden Datensatz aus der Datenbank abfragt. Die Syntax für diese Abfrage lautet:

SELECT news FROM newstabelle WHERE id = 1

Aus dem Querystring könnte mit PHP die Datenbankabfrage generiert werden:

$sql = 'SELECT news FROM newstabelle WHERE id =' . $_GET["id"];

Hier würde die ungeprüfte ID an die Datenbank geschickt werden. Tun Sie das niemals! Der offen sichtbare Querystring kann leicht manipuliert werden. Ein böswilliger Besucher könnte den Befehl, die gesamte Tabelle zu löschen, an die ID anhängen:

http://localhost/news.php?id=1;DELETE+FROM+newstabelle

Einzelne SQL-Anweisungen werden mit Semikolon getrennt. Im ungünstigsten Fall könnte das Skript in der Datei news.php aus diesem Querystring die folgende SQL-Anweisung generieren:

SELECT news FROM newstabelle WHERE id = 1; DELETE FROM newstabelle

Zugegeben, man muss dafür erst einmal den Tabellennamen herausfinden. Ein Blindversuch könnte aber von Erfolg gekrönt sein und fatale Folgen haben: Würden diese Anweisungen an die Datenbank geschickt werden, wäre die Tabelle newstabelle hiernach unwiederbringlich leer!

Selbst wenn dieser Fall nicht einträte, würden unter Umständen hässliche Fehlermeldungen ausgegeben, die peinlich und sicher nicht im Sinne des Webseitenbetreibers sind.

Überprüfen Sie also den Wert der übergebenen Variablen. Erlaubt sind in diesem Fall ausschließlich numerische Werte. Diese Prüfung kann mit Regulären Ausdrücken (dazu mehr im nächsten Kapitel) erfolgen oder mit der Funktion is_integer(), die den in den Klammern übergebenen Parameter darauf prüft, ob er eine Ganzzahl ist.

Oder Sie zwingen mindestens den Wert in den Integertyp, siehe Typen-Tricks im Handbuch. Andere Zeichen als Ziffern würden dann entfernt:

$sql = 'SELECT news FROM newstabelle WHERE id =' . (int)$_GET["id"];

Bei einem Manipulationsversuch könnte so im schlimmsten Fall kein Datensatz ausgelesen werden, wenn eine News mit dieser ID nicht existiert oder wenn die Konvertierung nach integer 0 ergeben hat, weil die Zeichenkette nicht mit einer Ziffern begann. Eine leere Datenbankabfrage werden Sie sowieso abfangen, insofern wäre das undramatisch.

Dieses Beispiel werden Sie besser verstehen, wenn Ihnen der Umgang mit Datenbanken geläufiger ist. Es zeigt jedoch so schön einleuchtend, was bei Unachtsamkeit des Programmierers passieren kann.

Beispiel: Inhalte über Querystring steuern

Ebenfalls schlimm sieht es aus, wenn Sie den Inhalt einer Seite über den Querystring steuern. Eigentlich eine komfortable Konstruktion, wenn man die externen Daten überprüft. Im Body könnte folgender Code stehen:

<a href="php1_w3_test03.php?datei=inhalt_A.inc.php">Inhalt A</a><br>
<a href="php1_w3_test03.php?datei=inhalt_B.inc.php">Inhalt B</a>

<?
if (isset($_GET["datei"]))
{
    include($_GET["datei"]);
}
?>

Beachten Sie, dass dieses Skript und die folgenden eine PHP-Fehlermeldung erzeugen werden, solange die Dateien inhalt_A.inc.php, inhalt_B.inc.php und home.inc.php nicht im gleichen Verzeichnis wie das Skript existieren. Wenn Sie dieses Beispiel nachvollziehen wollen, dann legen Sie drei leere Dateien an, in die Sie der Übersicht halber lediglich die Namen der Dateien schreiben. Sie sehen dann gleich, welche der Dateien geladen wurde.

Es wird lediglich geprüft, ob die Variable $_GET["datei"] existiert, weil PHP sonst bei include() ohne Parameter eine Fehlermeldung ausgeben würde. Dann wird der Inhalt der Variablen ohne weitere Prüfung in das Programm geladen. Auch hier kann der offene Querystring wieder leicht manipuliert werden:

http://localhost/php1_w3_test03.php?datei=http://www.akademie.de
http://localhost/php1_w3_test03.php?datei=etc/passwd

Der erste URI entführt den Benutzer, der zweite URI mit seiner relativen Pfadangabe lädt die Anzeige einer Passwortdatei vom Webserver. Hierin sind alle Passwörter aller Benutzer dieses Webservers abgelegt! Der Querystring könnte auch auf eine bösartige Datei verweisen, die Ihre Webseite, die Datenbank oder auch den gesamten Webserver ausspioniert.

Auch hier hilft es, wenn Sie - wie im Beispiel mit den Hintergrundfarben - ganz einfach die Variable aus dem Querystring auf erlaubte Werte überprüfen. Schreiben Sie die erlaubten Dateien in ein Array und überprüfen Sie, ob der per Querystring übergebene Wert im Array enthalten ist. Dieses Mal gehen wir sogar noch ein wenig weiter, wollen wir doch dem Benutzer unsere Dateistruktur nicht transparent machen. Im Querystring wird lediglich eine Ziffer übergeben, mit deren Hilfe wir im Programm dann den entsprechenden Dateinamen aus dem Array holen. Falls die Variable einen Wert hat, der nicht erlaubt ist, wird in diesem Beispiel die Homepage geladen.

$arrDateien = array(1 => "inhalt_A.inc", 
                    2 => "inhalt_B.inc");


if (array_key_exists($_GET["datei"], $arrDateien))
{
    include($arrDateien[$_GET["datei"]]);
}
else
{
    include("home.inc");
}

Die Funktion array_key_exists() prüft, ob der genannte Schlüssel im Array enthalten ist. Ist er vorhanden, wird die Variable $_GET["datei"] als Schlüssel für das Array $arrDateien verwendet und die entsprechende Datei wird eingebunden. Gibt es den Schlüssel nicht, wird die Homepage geladen.

Seien Sie übrigens zurückhaltend mit Fehlermeldungen in der Art "Einbruchversuch abgewehrt". Manche Programmierer machen das gern, um zu zeigen, dass sie schlauer sind als die Hacker. Allerdings kann es auch einem ganz unbedarften Benutzer passieren, dass er in diesem konkreten Beispiel eine falschen Querystring erzeugt, indem er zum Beispiel den Link auf diese Seite kopiert, und beim Kopieren ein Teil des Links verloren hat. Dieser Benutzer wäre zu Recht verärgert, wenn Sie ihm einen Manipulationsversuch unterstellten. Es reicht völlig, einen Fehler zu unterbinden.

In diesem Fall wird die im Tipp oben vorgestellte Kurzschreibweise für if-else-Anweisungen übrigens leider nicht funktionieren. Bei include() müssen Sie die klassische Schreibweise verwenden und auch die geschweiften Klammern auf jeden Fall setzen.

Diese Beispiele sollten Ihnen einige Anwendungsmöglichkeiten von Querystrings gezeigt, die Probleme bei der Übernahme von externen Variablen in unsere Programme aufgezeigt und einige kleine Kniffe vermittelt haben, wie die Überprüfung von Variablen erfolgen kann.

Als Mitglied können Sie diesen Beitrag weiterlesen!

Werden Sie Mitglied und testen Sie akademie.de 14 Tage lang kostenlos!

In den ersten 14 Tagen haben Sie Zugriff auf alle Inhalte auf akademie.de, außer Downloads. Sie können in dieser Zeit ohne Angabe von Gründen stornieren. Eine E-Mail an service@akademie.de genügt. Nur wenn Sie Mitglied bleiben, wird der Mitgliedsbeitrag nach Ende der 14tägigen Stornofrist abgebucht.

Ich bin bereits Mitglied
Jetzt Mitglied werden und akademie.de 14 Tage kostenlos testen
Ich entscheide mich für folgende Zahlungsweise:
14 Tage Stornorecht:
Ich kann meine Mitgliedschaft in den ersten 14 Tagen jederzeit formlos stornieren, z.B. per E-Mail an service@akademie.de.

Inhalt

Downloads zu diesem Beitrag

Newsletter abonnieren