Anzeigen - Jobelmann Schule

Transcription

Anzeigen - Jobelmann Schule
Lutz Kleinostendarp
Berufliches Gymnasium Technik
Informationstechnik
Unterrichtsskript zum Lerngebiet IT3:
Software zur Prozessdatenverarbeitung
entwickeln
Einführung in die Programmierung
mit PHP und MySQL
Stand: 04.02.2015
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 1 von 54
Inhaltsverzeichnis
1
1.1
1.2
1.3
HTML für PHP................................................................................................................................. 3
Eine einfache Seite ................................................................................................................ 3
Formulare ............................................................................................................................... 4
Tabellen.................................................................................................................................. 4
2
Einbettung von PHP in HTML ......................................................................................................... 6
3
Kommentare ................................................................................................................................... 7
4
4.1
4.2
4.3
Variablen, Datentypen und Operatoren .......................................................................................... 8
Regeln für Variablennamen ................................................................................................... 8
Zahlenvariablen und Rechenoperatoren ................................................................................ 8
Textvariablen .......................................................................................................................... 9
5.1
5.2
5.3
Formularauswertung ..................................................................................................................... 11
Eingabenformular ................................................................................................................. 11
Auswertung mit $_POST ...................................................................................................... 12
Umwandlung von Zeichenketten in Zahlen .......................................................................... 13
5
6
Kontrollstrukturen .......................................................................................................................... 15
6.1
Operatoren ........................................................................................................................... 15
6.1.1
Vergleichsoperatoren .................................................................................................. 15
6.1.2
logische Operatoren .................................................................................................... 15
6.1.2.1
Logisches ODER ..................................................................................................... 15
6.1.2.2
Logisches UND ....................................................................................................... 15
6.1.2.3
Logisches NICHT .................................................................................................... 16
6.1.3
Rangordnung der Operatoren ..................................................................................... 16
6.2
Verzweigungen .................................................................................................................... 16
6.2.1
Einseitige Auswahl ...................................................................................................... 16
6.2.2
Zweiseitige Auswahl .................................................................................................... 18
6.2.3
Geschachtelte Auswahl ............................................................................................... 18
6.2.4
Mehrfachauswahl ........................................................................................................ 19
6.2.5
HTML in Verzweigungsblöcken ................................................................................... 20
6.3
Schleifen............................................................................................................................... 21
6.3.1
for-Schleife .................................................................................................................. 21
6.3.2
while-Schleife .............................................................................................................. 23
6.3.3
do-while-Schleife ......................................................................................................... 25
6.3.4
foreach-Schleife........................................................................................................... 25
7
7.1
7.2
Felder ............................................................................................................................................ 26
Numerisch indizierte Felder ................................................................................................. 26
Assoziative Felder ................................................................................................................ 27
8.1
8.2
8.3
8.4
8.5
8.6
8.7
Datenbankverbindung ................................................................................................................... 29
Der erste Kontakt ................................................................................................................. 29
Datensätze auswählen ......................................................................................................... 31
Ausgabe in eine HTML-Tabelle ........................................................................................... 32
Auswahl von Daten in einem Suchformular ......................................................................... 33
Exkurs: Rekursiver Aufruf der gleichen Datei ...................................................................... 35
Datensätze erzeugen ........................................................................................................... 37
Datensätze ändern ............................................................................................................... 38
8
9
Zugriffsautorisierung ..................................................................................................................... 41
9.1
Benutzerregistrierung ........................................................................................................... 42
9.1.1
Identifizierung .............................................................................................................. 42
9.1.2
Kennwörter .................................................................................................................. 42
9.2
Benutzerauthentifizierung .................................................................................................... 43
9.2.1
HTTP-Authentifizierung ............................................................................................... 44
9.2.2
Session-Daten in der URL ........................................................................................... 44
9.2.3
Cookies ........................................................................................................................ 45
Seite 2 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
9.3
Statuserhalt durch Sessions ................................................................................................ 46
9.3.1
Das Session-Management von PHP ........................................................................... 47
9.3.2
Freizügigkeit einer PHP-Session................................................................................. 47
9.3.3
Daten einer Session verwalten .................................................................................... 48
9.3.4
Beispiel: Session zur Benutzerauthentifizierung ......................................................... 48
10 Angriffsszenarien .......................................................................................................................... 51
10.1
Informationsgewinnung ........................................................................................................ 51
10.2
Parametermanipulation ........................................................................................................ 51
10.3
Cross-Site-Scripting ............................................................................................................. 51
10.4
SQL-Injection ....................................................................................................................... 51
10.4.1
Get-Parameter ............................................................................................................. 52
10.4.2
POST-Parameter ......................................................................................................... 52
10.4.3
Cookie-Parameter ....................................................................................................... 52
10.4.4
Schutz vor SQL-Injektion ............................................................................................. 52
10.5
Autorisierung und Authentifizierung ..................................................................................... 53
10.5.1
Man-in-the-Middle-Attacke .......................................................................................... 53
10.5.2
Wörterbuchangriff ........................................................................................................ 53
10.5.3
Social Engineering....................................................................................................... 54
11
Objektorientierte Programmierung in PHP 5 ................................................................................ 55
Anhang: Verzeichnisse .......................................................................................................................... 56
Einführung in die Programmierung mit PHP und MySQL.doc
1
Seite 3 von 54
HTML für PHP
In diesem Abschnitt werden die Bestandteile von HTML1, die zur Bearbeitung der PHP2Programme notwendig sind, dargestellt. Dies sind: Dokumentaufbau, Formulare und Tabellen.
Zum Erlernen der Programmiersprache PHP, zum Ausprobieren der Beispiele und zum Lösen
der Übungen muss man nur wenige Grundlagen von HTML beherrschen. Zum Testen benötigt
man einen Texteditor und einen Web-Browser
Zum Erzeugen von ansprechenden Websites, also mehreren miteinander verknüpften Seiten,
sind allerdings genauere Kenntnisse notwendig.
1.1
Eine einfache Seite
Innerhalb einer HTML-Seite befinden sich Text und Markierungen, die in spitzen Klammern
eingebunden sind. Viele dieser Markierungen sind so genannte Container, das heißt, es gibt
jeweils eine Anfangsmarkierung und eine Endmarkierung.
Innerhalb des Containers <html> befindet sich das gesamte Dokument. Es besteht aus den
Containern <head> und <body>. Im Container <body> steht der eigentliche Inhalt des
Dokuments.
<html>
<head>
<title> Meine erste Internetseite </title>
</head>
<body>
Das ist der erste Text der Internetseite.
</body>
</html>
Listing 1-1:
PHP1-1.htm
Geben Sie das obige Beispiel mithilfe eines Editors ein. Speichern Sie es unter dem Dateinamen
PHP1-1.htm in einem Verzeichnis ihrer Wahl. Laden Sie die Datei in einen Web-Browser.
Abbildung 1-1: PHP1-1.htm
1
2
Hypertext Markup Language, eine textbasierte Auszeichnungssprache zur Strukturierung von Inhalten
ursprünglich „Personal Home Page Tools“, jetzt ein rekursives Akronym für PHP: Hypertext Preprocessor
Seite 4 von 54
1.2
Einführung in die Programmierung mit PHP und MySQL.doc
Formulare
Eine besondere Stärke von PHP ist die einfache Auswertung von Formularinhalten. Durch eine
solche Auswertung wird die Informationsübermittlung vom Betrachter der Webseite zum
Webserver ermöglicht.
Der HTML-Code:
<html>
<body>
Bitte tragen Sie Ihren Namen ein<br> und senden Sie das Formular
ab.<br>
<form>
<input type = "text" name="vorname" size="30"> Vorname <br>
<input type = "text" name="nachname" size="30"> Nachname<br>
<input type="submit">
<input type="reset">
</form>
</body>
</html>
Listing 1-2:
PHP1-2.htm
Geben Sie das obige Beispiel einen und speichern Sie es unter dem Dateinamen PHP1-2.htm. In
diesem Formular kann der Betrachter zwei Eintragungen vornehmen und das Formular
absenden. Es fehlt allerdings noch ein passendes Server-Programm. Deshalb erfolgt bisher noch
keinerlei Reaktion.
Abbildung 1-2: PHP1-2.htm
1.3
Tabellen
Tabellen dienen zur übersichtlicheren Darstellung größerer Datenmengen und zur mehrspaltigen
Ausgabe in Dokumenten. Damit eignen sie sich besonders zur Ausgabe von Datenbankinhalten.
Auch Formulare lassen sich mit Tabellen formatieren.
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 5 von 54
<html>
<body>
Bitte tragen Sie Ihren Namen ein<br>
und senden Sie das Formular ab.<br>
<form>
<table border=”0”>
<tr>
<td>Vorname</td>
<td><input name=”vorname” size="30"></td>
</tr>
<tr>
<td>Nachname</td>
<td><input name=”nachname" size="30"></td>
</tr>
</table>
<input type="submit">
<input type="reset">
</form>
</body>
</html>
Listing 1-3:
PHP1-3.htm
Speichern Sie das obige Programm unter dem Namen PHP1-3.htm. Das Programm
unterscheidet sich nur in der Anordnung von Bezeichner und Formularfeld von dem
vorhergehenden.
Abbildung 1-3: PHP1-3.htm
Seite 6 von 54
2
Einführung in die Programmierung mit PHP und MySQL.doc
Einbettung von PHP in HTML
Eine grundsätzliche Bemerkung zu Beginn. In den folgenden Kapiteln sollen nicht nur die
Grundkenntnisse der Sprache PHP vermittelt werden, sondern auch ein übersichtlicher,
strukturierter Programmierstil. Nach meiner Erfahrung vereinfacht dies sowohl die Arbeit eines
einzelnen Entwicklers als auch die Zusammenarbeit eines Entwickler-Teams.
Grundsätzlich gibt es mehrere Wege, PHP-Programme in HTML-Dateien einzubetten. In den
meisten PHP-Programmen wird jedoch die folgende Methode verwendet:
<?php
[PHP-Anweisung];
[PHP-Anweisung];
[PHP-Anweisung];
?>
Die Markierung <?php leitet eine einzelne PHP-Anweisung oder einen Block von PHPAnweisungen ein. Diese werden bis zur Markierung ?> bearbeitet, die das Ende des Blocks
darstellt. Jede PHP-Anweisung wird mit einem Semikolon abgeschlossen.
PHP-Blöcke können im gesamten Dokument untergebracht werden. Der Code wird von oben
nach unten abgearbeitet und es kann mehrmals zwischen HTML und PHP gewechselt werden.
Das folgende Beispiel verdeutlicht die Einbettung von PHP-Code in HTML:
<html>
<head>
<title> Titelzeile der Datei</title>
</head>
<body>
<p>Die erste Zeile in HTML</p>
<?php echo "<p>Die zweite Zeile in PHP</p>"; ?>
<p>Die dritte Zeile in HTML</p>
<?php
echo "<p>Die vierte Zeile in PHP</p>";
echo "<p>Die fünfte Zeile in PHP</p>";
?>
</body>
</html>
Listing 2-1:
PHP2-1.php
Speichern Sie das obige Programm unter dem Namen
PHP2-1.php ab. Dieses Programm ist nicht direkt im Browser
lauffähig. PHP ist eine serverseitige Sprache. Es ist deshalb
Abbildung 2-1: PHP2-1.php
notwendig, dass die Datei auf einem Web-Server ausgeführt wird.
In der Installation von XAMPP liegen alle Web-Dokumente im
Verzeichnis htdocs unterhalb des Hauptverzeichnisses xampp. Der Apache-Server übergibt alle
Dateien mit der Endung .php zuerst dem PHP-Interpreter, bevor sie an den Client ausgeliefert
werden.
Das Programm kann durch den folgenden Befehl in einem Browser (Eingabe in die
Adressleiste!) auf dem Server ausgeführt werden: localhost/PHP2-1.php
Einführung in die Programmierung mit PHP und MySQL.doc
3
Seite 7 von 54
Kommentare
Durch Kommentare wird ein Programm lesbar. Sie werden nicht ausgeführt, sondern dienen
lediglich der Information des Entwicklers. Sollte es sich um eine Gruppe von Entwicklern
handeln oder sollte das Programm später von anderen Entwicklern weiter bearbeitet werden, so
ist eine ausführliche Kommentierung der eigenen Programmzeilen unerlässlich.
Erfahrungsgemäß gibt es immer wieder Entwickler, die ihre Programme nur minimal
kommentieren. Dies führt häufig zu Programmen, die (auch von dem ursprünglichen
Programmierer) nicht oder nur unter größtem Aufwand weiterzuentwickeln sind.
Man unterscheidet zwischen einzeiligen und mehrzeiligen Kommentaren:
 ein einzeiliger Kommentar beginnt mit den Zeichen // und endet am Ende der Zeile. Er wird
im Allgemeinen zur Kommentierung einzelner Programmschritte verwendet.
 Eine mehrzeiliger Kommentar beginnt mit den Zeichen /* und endet mit den Zeichen */. Er
wird üblicherweise zur Erläuterung eines ganzen Programmblocks verwendet.
Ein Beispiel (PHP3-1.php):
<html>
<body>
<?php
echo "Das ist der Anfang"; // Kommentar
// bis zum Zeilenende
/* Ein Kommentar über
mehrere Zeilen hinweg */
echo " und hier das Ende des Programms";
?>
</body>
</html>
Listing 3-1:
PHP3-1.php
Abbildung 3-1: PHP3-1.php
Seite 8 von 54
4
Einführung in die Programmierung mit PHP und MySQL.doc
Variablen, Datentypen und Operatoren
Innerhalb eines Programms können Informationen zur späteren Verwendung in Variablen
gespeichert werden. Für diese Variablen unterstützt PHP die folgenden Datentypen:





ganze Zahlen
Zahlen mit Nachkommastellen
Zeichenketten
Felder (ein- und mehrdimensional)
Objekte
Der Datentyp für eine Variable wird nicht vom Programmierer festgelegt, sondern richtet sich
nach dem Zusammenhang der Verwendung. Eine Variable kann ihren Datentypen innerhalb
eines Programms wechseln. Dies bedeutet, dass in PHP keine Variablendeklaration stattfindet
und eine Variable bei ihrem ersten Erscheinen sofort benutzt werden kann.
4.1
Regeln für Variablennamen
Für die Namen von Variablen (und später auch Funktionen) gelten folgende Regeln:
 Sie müssen mit einem Dollarzeichen "$" beginnen.
 Sie dürfen keine Leerzeichen enthalten.
 Sie dürfen nur aus Buchstaben und Ziffern bestehen. Dabei muss das erste Zeichen ein
Buchstabe sein. Es wird zwischen Groß- und Kleinschreibung unterschieden.
 Sie dürfen keine deutschen Umlaute oder sonstige Sonderzeichen enthalten. Als einziges
Sonderzeichen ist der Unterstrich "_" erlaubt.
 Sie dürfen mit keinem reservierten Wort identisch sein.
Es empfiehlt sich, selbst erklärende Namen zu vergeben. Dadurch wird nicht nur der
Programmcode besser lesbar, sondern auch Fehler durch die Verwendung falscher Variablen weit
gehend vermieden.
4.2
Zahlenvariablen und Rechenoperatoren
Mit dem folgenden Programm soll der Preis für eine Tankfüllung Benzin berechnet werden.
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 9 von 54
<html>
<body>
<?php
$liter = 14;
$preis = 1.35;
$zahlung = $liter * $preis;
echo $zahlung;
?>
</body>
</html>
Listing 4-1:
PHP4-1.php
Abbildung 4-1:
PHP4-1.php
Der Ablauf des Programms kann hier wie folgt beschrieben werden:
Die zwei Variablen $liter und $preis werden eingeführt und ihnen werden Werte
zugewiesen. Wie zu erkennen ist, handelt es sich im ersten Fall um eine Ganzzahl, im zweiten Fall
um eine Zahl mit Nachkommastellen. Zu beachten ist, dass als Dezimaltrennzeichen ein Punkt
zu verwenden ist. Die beiden Variablen werden multipliziert und das Ergebnis der dritten
Variablen zugewiesen. Der Inhalt dieser dritten Variablen wird dann mit dem Befehl echo
ausgegeben.
Operator
+
*
/
%
+=
-=
Tabelle 1:
Bedeutung
Addition
Subtraktion
Multiplikation
Division
Modulo (Rest einer Ganzzahldivision)
Kombinationsanweisung: $x += 3; erhöht den Wert von $x um 3
Kombinationsanweisung: $x -= 3; verringert den Wert von $x um 3
Rechenoperatoren
Für Rechnungen können die üblichen arithmetischen Operatoren verwendet werden. Bei der
Berechnung gelten die in der Mathematik üblichen Prioritäten. Also z.B. Punkt- vor
Strichrechnung. Außerdem findet die Abarbeitung der Ausdrücke von links nach rechts statt. Die
Reihenfolge kann allerdings mit dem Setzen von Klammern beeinflusst werden.
Übung 4.1: Erweitern Sie das Beispielprogramm dahingehend, dass drei verschiedene
Litermengen eingelesen werden und am Ende ein Gesamtpreis ausgegeben wird.
Übung 4.2: Berechnen Sie in einem PHP-Programm den Bruttopreis eines Einkaufs. Es wurden
drei Artikel gekauft. Die Nettopreise der Artikel betragen: 22,50 €, 12,30 € und 5,20 €. Der
Bruttopreis berechnet sich bekanntlich aus dem Nettopreis zuzüglich 19% Umsatzsteuer.
4.3
Textvariablen
Zeichenketten müssen in einfache oder doppelte Hochkommata eingeschlossen werden. Das
Zeichen "." (Punkt) dient der Verkettung mehrerer Zeichenketten oder Zahlen miteinander. Dies
kann auch für eine Kombination von Konstanten und Variablen genutzt werden. Auch hier kann
die Kombinationsanweisung ".=" (Punkt + Gleich) zur Vergrößerung einer Zeichenkette
eingesetzt werden. Falls die Zeichenketten HTML-Code enthalten, so gelangt dieser HTMLCode zur Ausführung.
Seite 10 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
<html>
<body>
<?php
$liter = 14;
$preis = 1.35;
$zahlung = $liter * $preis;
$einheit1 = "Liter";
$einheit2 = "Euro";
$gesamt = "Tankfüllung: " . $liter . " " . $einheit1;
$gesamt.= " kosten " . $zahlung . " " . $einheit2 . "<br>";
echo $gesamt;
echo "Tankfüllung: $liter $einheit1 kosten $zahlung $einheit2<br>";
echo 'Tankfüllung: $liter $einheit1 kosten $zahlung $einheit2<br>';
?>
</body>
</html>
Listing 4-2:
PHP4-2.php
Das Programm ist eine Erweiterung der Preisberechnung des letzten Kapitels. Der Variablen
$gesamt wird eine Zeichenkette zugewiesenen, die sich aus Text- und Zahlenvariablen
zusammensetzt. In einer zweiten Zeile wird diese Variable verlängert. Die Textausgabe erfolgt auf
drei Arten:
1. Ausgabe der Variablen.
2. Direkte Ausgabe der zusammengesetzten Zeichenkette in doppelten Hochkommata.
3. Direkte Ausgabe der zusammengesetzten Zeichenkette in einfachen Hochkommata.
Abbildung 4-2: PHP4-2.php
Nach der Ausführung im Browser ist zu erkennen, dass die zweite Variante in der Ausgabe der
ersten entspricht. In der dritten Variante werden statt der Werte die Namen der Variablen
ausgegeben. Dies ist normalerweise nicht erwünscht.
Einführung in die Programmierung mit PHP und MySQL.doc
5
Seite 11 von 54
Formularauswertung
Bisher hatte der Benutzer eines Programms noch keine Möglichkeit, eigene Eingaben
vorzunehmen. Alle Werte mussten direkt in das Programm eingetragen sein, er konnte nur das
Ergebnis betrachten.
PHP kommt jedoch typischerweise gerade bei der Auswertung von Benutzereingaben aus
Formularen zum Einsatz. Hierdurch wird die dynamische Informationsübermittlung zwischen
Benutzer und Webserver überhaupt erst ermöglicht.
Der Ablauf ist dabei typischerweise wie folgt: Zunächst erhält der Nutzer ein Formular, in dem er
eigene Einträge vornehmen kann beziehungsweise unter vorgefertigten Einträgen auswählt. Nach
dem Ausfüllen sendet er das Formular ab und erhält nach der Auswertung die Antwort vom
Webserver. In dieser einführenden Betrachtung soll die Datenübertragung mithilfe von
einzeiligen Text-Eingabefeldern ermöglicht werden. Grundsätzlich können aber auch in PHP alle
Formularelemente3 verwendet werden.
5.1
Eingabenformular
Der HTML-Programmcode des Formulars:
<html>
<body>
Bitte tragen Sie Ihren Vornamen und Ihren Nachnamen ein.<br>
Senden Sie anschließend das Formular ab.<br>
<form action = "PHP5-1.php" method = "post">
<input type = "text" name = "vorname"> Vorname <br>
<input type = "text" name = "nachname"> Nachname <br>
<input type = "submit">
<input type = "reset">
</form>
</body>
</html>
Listing 5-1:
PHP5-1.htm
Innerhalb des HTML-Dokuments befindet sich ein form-Container. Dieser beinhaltet in seinem
Start-Tag:
 das Attribut action, das auf eine Datei mit dem PHP-Auswertungsprogramm verweist.
Hier: PHP5-1.php.
 Das Attribut method, welches die Übertragungsmethode zum Webserver kennzeichnet
(hier: post).
Innerhalb des form-Containers befinden sich die verschiedenen Formularelemente.
3
Zum Einsatz von Formularelementen in HTML siehe z.B. de/selfhtml.org
Seite 12 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Abbildung 5-1: PHP5-1.htm
Erweitern Sie das Beispiel so, dass eine ganze Adresse eingegeben werden kann.
Zusätzlich sollen also Eingabefelder für Straße, Hausnummer, Postleitzahl und Ort im Formular
vorhanden sein.
Übung 5.1:
5.2
Auswertung mit $_POST
Das Programm PHP5-1.htm verweist auf das Programm PHP5-1.php. Dieses auswertende PHPProgramm sieht wie folgt aus:
<html>
<body>
<?php
echo "Guten Tag, " . $_POST["vorname"] . " " . $_POST["nachname"];
?>
</body>
</html>
Listing 5-2:
PHP5-1.php
Die Ergebnisausgabe könnte dann so aussehen:
Es gibt in PHP einige vordefinierte Variablen, darunter
das assoziative Feld4 $_POST. Die Namen der
Formular-Eingabefelder werden automatisch zu
Elementen dieses Feldes umgewandelt, sofern die
Übertragungsmethode post verwendet wurde.
Assoziative Felder sind Arrays, deren Elemente mit
einem Namen angesprochen werden können. Aus dem
Text-Eingabefeld vorname wird somit der Wert
$_POST["vorname"] des Feldes.
4
vergleiche hierzu Kapitel 7.2
Abbildung 5-2: PHP5-1.php
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 13 von 54
Feld-Elemente dürfen allerdings nicht unmittelbar innerhalb einer Zeichenkette ausgegeben
werden, wie dies bei einzelnen Variablen erlaubt ist. Hierdurch gerät die Ausgabezeile etwas
umfangreicher.
Statt mit der Methode post kann ein Formular auch mit der Methode get5 verwendet werden.
In diesem Fall ersetzt das Feld $_GET das Feld $_POST. Im Allgemeinen ist aber die Methode
post zu bevorzugen, da sie sicherer und universeller ist.
Erweitern Sie die Ergebnisdatei derart, dass sie alle Eingabefelder aus Übung 5.1
wiedergeben kann. Die Ausgabe im Browser soll wie folgt aussehen:
Übung 5.2:
Abbildung 5-3: Uebung5-2.php
5.3
Umwandlung von Zeichenketten in Zahlen
Ein Texteingabefeld eines Formulars gibt immer eine Zeichenkette aus. Auch an das PHPProgramm wird eine Zeichenkette übermittelt. Häufig soll jedoch Zahlen, zum Beispiel zur
Ausführung von Berechnungen, ermittelt werden. Dazu sind die folgenden Regeln zu beachten.
Entscheidend für die Konvertierung einer Zeichenkette ist ihr Beginn. Beginnt die Zeichenkette
mit gültigen numerischen Zeichen, so werden diese genutzt. Andernfalls ergibt sich der Wert 0.
Gültige Elemente von numerischen Zeichen sind:




ein Vorzeichen (optional)
Ziffern
ein Dezimalpunkt (optional)
ein Exponent (optional). Der Exponent ist ein kleines "e" oder ein großes "E", gefolgt von
einer oder mehreren Ziffern.
Die Zeichenkette wird wie folgt interpretiert:
 als ganze Zahl, falls sie nur aus Ziffern bestellt
 als Zahl mit Nachkommastellen, falls sie neben den Ziffern die Zeichen "." (Punkt), "e" oder
"E" beinhaltet.
5
Daten werden bei der Methode „get“ in der URI übertragen (www.meineseite.de?daten=keine) während die Methode „post“
diese im Body der Nachricht (also unsichtbar) überträgt.
Seite 14 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Beispiele
Zeichenkette
"234
"234xy"
"xy234"
"23.4"
"23.4xy"
"xy23.4"
"-234"
"23e4"
"23e-4"
Tabelle 2:
Wert
234
234
0
23.4
23.4
0
-234
230000
0.0023
Datentyp
ganze Zahl
ganze Zahl
Zeichenkette
Zahl mit Nachkommastellen
Zahl mit Nachkommastellen
Zeichenkette
ganze Zahl
Zahl mit (möglichen) Nachkommastellen
Zahl mit Nachkommastellen
Umwandlung von Zeichenketten in Zahlen
Sofern man sichergehen möchte, dass eine Variable als Zahlenwert interpretiert wird, kann man
die Umwandlung explizit vornehmen. Hierzu dienen die beiden Funktionen doubleval()
und intval(). Die erste der beiden Funktionen wandelt dabei immer in eine Zahl mit
Nachkommastellen um, die zweite erzeugt eine ganze Zahl.
In Anlehnung an C ist auch eine Typumwandlung als sogenannte Cast-Operation möglich. Dabei
gibt man den gewünschten Datentyp in Klammern vor der umzuwandelnden Variablen an. Die
Anweisung $zahl = (int) $zahl wandelt die Variable $zahl z.B. in eine ganze Zahl um.
Folgende Umwandlungen sind möglich:
(int), (integer)
 Integer, Ganzzahl
(bool), (boolean)
 Boolean, Wahrheitswert
(float), (double), (real)  float, Kommazahl
(string)
 string, Zeichenkette
(array)
 Array
(object)
 Objekt
Dabei sind nicht alle Umwandlungsmöglichkeiten sinnvoll.
In den Beispielen dieses Skripts werden Eingabefehler des Benutzers nicht immer abgefangen. In
realen Programmen sollte man aber soweit wie möglich Routinen einbauen, die Eingabefehler
erkennen. Grundsätzlich gilt aber immer der Grundsatz: Kein Programm ist vollständig gegen
Eingabefehler geschützt.
Erstellen Sie ein Formular, in dem der Benutzer aufgefordert wird, zwei Zahlen
einzugeben und das Formular abzusenden. Erstellen Sie ein PHP-Programm, das die Summe
dieser beiden Zahlen ermittelt und das Ergebnis ausgibt.
Übung 5.3:
Einführung in die Programmierung mit PHP und MySQL.doc
6
Seite 15 von 54
Kontrollstrukturen
Bisher wurden alle Dateien rein sequenziell abgearbeitet. Auch ein PHP-Programm muss aber in
der Lage sein, ebenso wie andere Programme, auf unterschiedliche Bedingungen zu reagieren. Bei
den Kontrollstrukturen unterscheiden wir zwischen Verzweigungen und Schleifen. Da die
grundsätzliche Funktion sich nicht von der in anderen Programmiersprachen unterscheidet,
werden wir uns hier im Wesentlichen auf die Syntax innerhalb eines PHP-Programms
beschränken.
6.1
6.1.1
Operatoren
Vergleichsoperatoren
Ob eine Anweisung ausgeführt wird oder nicht, wird mithilfe von Wahrheitswerten entschieden.
Diese sind das Ergebnis von Vergleichsoperationen. Die Vergleichsoperatoren entsprechen
denen anderer Programmiersprachen wie C++ oder Java und sind in der folgenden Tabelle
dargestellt.
Operator
==
!=
>
<
>=
<=
Tabelle 3:
6.1.2
Bedeutung
Gleichheit
Ungleichheit
größer als
kleiner als
größer oder gleich
kleiner oder gleich
gilt
für Zahlen und Zeichenketten
für Zahlen und Zeichenketten
nur für Zahlen
nur für Zahlen
nur für Zahlen
nur für Zahlen
Vergleichsoperatoren
logische Operatoren
Es kommt häufig vor, dass mehrere Bedingungen miteinander verknüpft werden müssen. Hierzu
benötigt man die logischen Operatoren.
6.1.2.1 Logisches ODER
Das logische ODER (Zeichen || oder OR) wird verwendet, wenn nur eine von mehreren
Bedingungen zutreffen muss. Dabei ist unbedingt zu beachten, dass jede der beiden einzelnen
Bedingungen vollständig formuliert wird. Die Aussage
pw == "bingo" || pw == "cool"
ergibt wahr, wenn in die Variable pw entweder der Wert "bingo" oder der Wert "cool"
eingegeben wurde.
6.1.2.2 Logisches UND
Das logische UND (Zeichen && oder AND) wird verwendet, wenn alle Bedingungen zutreffen
müssen. Die Aussage
bn == "bingo" && pw = "cool"
Seite 16 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
ergibt wahr, wenn die Variable bn den Wert "bingo" und die Variable pw den Wert "cool"
enthält.
6.1.2.3 Logisches NICHT
Mithilfe des Operators NICHT (Zeichen !) kann man den Wahrheitswert von Bedingungen
umkehren. Dies ist insbesondere bei komplexeren logischen Verknüpfungen hilfreich. Die
folgende Aussage ergibt in jedem Fall den Rückgabewert wahr:
pw == "bingo" || !(pw == "bingo")
6.1.3
Rangordnung der Operatoren
Ausdrücke mit mehreren Operatoren werden von links nach rechts unter Beachtung der
Rangordnung aufgelöst. Im Folgenden eine Tabelle der Rangordnung der bisher beschriebenen
Operatoren. Es wird mit der höchsten Stelle der Rangordnung begonnen.
Operatoren
()
!, *, /, %
+< , <= , > , >=
==, !=
&&
AND
||
OR
=
Tabelle 4:
Bedeutung
Klammern
logisches NICHT; negatives Vorzeichen
Multiplikation; Division; Modulo
Addition; Subtraktion
kleiner; kleiner oder gleich; größer; größer oder gleich
gleich; ungleich
logisches UND
logisches ODER
Zuweisung
Rangordnung der Operatoren
Klammern stehen an der höchsten Stelle der Rangordnung. Mit ihrer Hilfe kann also die
Rangfolge der Operatoren beeinflusst werden. Im Zweifelsfall ist es empfehlenswert, zusätzliche
Klammern zu verwenden.
6.2
Verzweigungen
In Verzweigungen wird die Ausführung einer Anweisung von einer oder mehreren Bedingungen
abhängig gemacht. Je nachdem, ob die Bedingung zutrifft, werden die entsprechenden
Anweisungen ausgeführt oder nicht. Wie die meisten modernen Programmiersprachen kennt
PHP einseitige, zweiseitige oder mehrseitige Auswahlbedingungen.
6.2.1
Einseitige Auswahl
Die einfache if-Anweisung wird hier als bekannt vorausgesetzt und deshalb nur mit einem
kleinen Beispiel vorgestellt.
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 17 von 54
<html>
<body>
<?php
$preis = 0.98;
if ($preis < 1) echo "Der Preis liegt unter 1 Euro";
?>
</body>
</html>
Listing 6-1:
PHP6-1.php
Das Beispiel zeigt zwei Besonderheiten:
 Die Bedingung muss in Klammern stehen.
 Eine einfache Anweisung kann unmittelbar auf die Bedingung folgen.
Sollen allerdings aufgrund einer Bedingung mehrere Anweisungen ausgeführt werden, so müssen
diese innerhalb geschweifter Klammern stehen. Dieses nennt man einen Anweisungsblock. Das
folgende Beispiel ist um eine zweite Ausgabe erweitert.
<html>
<body>
<?php
$preis = 0.98;
if ($preis < 1){
echo "Der Preis liegt unter 1 Euro<br>";
echo "Das ist günstig";
}
?>
</body>
</html>
Listing 6-2:
PHP6.2.php
Grundsätzlich können die geschweiften Klammern des Anweisungsblocks in einer eigenen Zeile
oder mit in der Anweisungszeile stehen. Das obige Beispiel (öffnende Klammer in der
Bedingungszeile, schließende Klammer in einer eigenen Zeile) verbindet die Vorteile von
Übersichtlichkeit und Platzeinsparung. Wichtig ist dabei zur Übersichtlichkeit die Einrückung des
Anweisungsblocks.
Erstellen Sie ein Eingabeformular, in das sich der Preis eingeben lässt und werten sie
diese Eingabe mit dem obigen Programm (in leicht angepasster Form) aus. Achtung: Bei einem
Preis über 1 € erfolgt keine Ausgabe.
Übung 6.1:
Seite 18 von 54
6.2.2
Einführung in die Programmierung mit PHP und MySQL.doc
Zweiseitige Auswahl
Die if-else-Anweisung sieht ganz entsprechend aus:
<html>
<body>
<?php
$preis = 1.02;
if ($preis < 1){
echo "Der Preis liegt unter 1 Euro<br>";
echo "Das ist günstig";
}else{
echo "Der Preis liegt bei 1 Euro oder darüber<br>";
echo "Langsam wird es teuer";
}
?>
</body>
</html>
Listing 6-3:
PHP6-3.php
Übung 6.2: Verändern
Sie das Eingabeformular aus Übung 6.2Übung 6.1, so dass eine zweiseitige
Ergebnisauswahl stattfindet.
Erstellen Sie ein Formular, indem der Benutzer ein Zugangs Passwort eintragen soll
(ausnahmsweise in sichtbarer Form). Das PHP-Programm vergleicht die Eingabe mit dem
gespeicherten Passwort und reagiert entsprechend mit der Ausgabe "Zugang gestattet" oder
"Zugang verweigert".
Übung 6.3:
Übung 6.4: Erweitern
Sie Übung 6.3 für drei Passwörter.
Übung 6.5: Erweitern
Sie Übung 6.4, so dass auch ein zugehöriger Nutzername mitgeprüft wird.
6.2.3
Geschachtelte Auswahl
Die if-else-Verzweigung lässt sich auch schachteln, so dass mehr als zwei Fälle
unterschieden werden können.
<html>
<body>
<?php
$preis = 1.12;
if ($preis < 1){
echo "Der Preis liegt unter 1 Euro<br>";
echo "Das ist günstig";
}else{
if ($preis < 1.2){
echo "Der Preis liegt zwischen 1 Euro und 1.20 Euro<br>";
echo "Langsam wird es teuer";
}else{
echo "Der Preis liegt über 1.20 Euro<br>";
echo "Das ist viel zu teuer";
}
}
?>
</body>
</html>
Listing 6-4:
PHP6-4.php
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 19 von 54
Es soll der Preis für eine Tankfüllung berechnet werden. Drei Benzinsorten sind zu
berücksichtigen: Normal (Preis: 1,50 €), Super (Preis: 1,80 €) und Diesel (Preis: 1,35 €). Im
Eingabenformular soll in das erste Eingabefeld die getankte Literzahl und in das zweite
Eingabefeld entweder ein N, ein S oder ein D eingegeben werden. Das PHP-Programm ermittelt
abhängig von der Sorte und der Menge den zu zahlenden Betrag. Eine Prüfung auf Fehleingaben
findet nicht statt.
Übung 6.6:
6.2.4
Mehrfachauswahl
Die Mehrfachauswahl mit switch-case bietet für einen bestimmten Typ von Verzweigungen
eine andere Schreibweise. Sie kann eingesetzt werden, wenn die gleiche Variable auf mehrere
feste Werte geprüft werden soll. Diese Form ist bei vielen verschiedenen Prüfungen
übersichtlicher als die geschachtelte Verzweigung. Sie bietet aber keine Möglichkeit für eine
Bereichsprüfung. Übung 6.6 sieht mit switch-case wie folgt aus :
<html>
<body>
<?php
switch ($_POST ["sorte"]){
case "N":
$zahlung = $_POST ["liter"] * 1.50;
echo $_POST ["liter"] . " L Normal kosten $zahlung Euro";
break;
case "S":
$zahlung = $_POST ["liter"] * 1.80;
echo $_POST ["liter"] . " L Super kosten $zahlung Euro";
break;
case "D":
$zahlung = $_POST ["liter"] * 1.35;
echo $_POST ["liter"] . " L Diesel kosten $zahlung Euro";
break;
default:
echo "Als Sorte dürfen nur N, S oder D eingegeben werden!";
}
?>
</body>
</html>
Listing 6-5:
PHP6-5.php
Es wird ein so genannter switch-Block erzeugt. Innerhalb dieses switch-Blockes wird der
Wert von $_POST["sorte"] untersucht. Die vorhandenen Fälle werden der Reihe nach
verglichen. Sobald einer der Fälle zutrifft, werden die weiteren Anweisungen bearbeitet, bis man
auf die Anweisung break trifft. Die Anweisungen nach dem break werden nicht mehr
ausgeführt.
Die optionale Anweisung default ist dann nützlich, wenn keiner der genannten Fälle zutraf.
Im oben angegebenen Programm wird sie als Fehlerkontrolle genutzt, falls der Benutzer keine
erlaubte Sorte eingegeben hat.
Übung 6.7: Erweitern
Sie das Formular aus Übung 5.3 um ein Auswahlfeld zur Auswahl einer der
Rechenoperationen +, -, *, /. Erstellen Sie ein PHP-Programm, das die jeweils gewählte
Rechenoperation durchführt und das Ergebnis ausgibt.
Seite 20 von 54
6.2.5
Einführung in die Programmierung mit PHP und MySQL.doc
HTML in Verzweigungsblöcken
Falls innerhalb einer einfachen oder mehrfachen Verzweigung jeweils nur reiner HTML-Code
ohne PHP-Variablen ausgegeben werden soll, ist eine gemischte Schreibweise von PHP und
HTML möglicherweise einfacher.
Das folgende Beispiel zeigt, wie eine Verzweigung auf mehrere PHP-Blöcke verteilt werden kann.
Dazwischen steht reiner HTML-Code ohne echo, Anführungszeichen, Semikolon usw. Zu
beachten ist aber, dass nach der Bedingung if ($preis < 1) und der else-Anweisung
ein Doppelpunkt notiert werden muss. Dieser zeigt an, dass die Verzweigung noch nicht
abgeschlossen ist. Der folgende HTML-Code wird dann nur ausgeführt, wenn die Bedingung
zutrifft. Ansonsten wird mit dem nächsten Teil der Verzweigung (nächster PHP-Block)
fortgesetzt. Bei dieser Variante muss der Bedingungsblock am Ende explizit mit einem endif
abgeschlossen werden.
<html>
<body>
<?php
$preis = 1.12;
if ($preis < 1):
?>
Der Preis liegt unter 1 Euro<br>
Das ist günstig
<?php else: ?>
Der Preis liegt bei 1 Euro oder darüber<br>
Langsam wird es teuer
<?php endif; ?>
</body>
</html>
Listing 6-6:
PHP6-6.php
Einführung in die Programmierung mit PHP und MySQL.doc
6.3
Seite 21 von 54
Schleifen
Schleifen werden verwendet, um Anweisungen in Abhängigkeit der Laufzeitbedingungen
wiederholen zu können. PHP kennt die for- und die while-Schleife. Schleifen bergen immer
die Gefahr in sich, einen Zustand zu erreichen, in dem sie nicht mehr angebrochen werden
können. Man spricht dann von Endlosschleifen. Endlosschleifen machen sich durch
Programmabstürze bemerkbar. Das Programm "hängt sich auf" und muss von außen (über das
Betriebssystem) mit der Gefahr von Datenverlust beendet werden.
6.3.1
for-Schleife
Die for-Schleife wird benutzt, um eine feste Anzahl von Wiederholungen zu erzeugen
(Zählschleife). In seltenen Fällen ist sie Zahl der Wiederholungen schon während der
Programmierung bekannt und kann als Konstante eingetragen werden. In den meisten Fällen
ergibt sich die Anzahl während des Programmlaufs und wird dann als Variablenwert eingebracht.
<html>
<body>
<?php
for ($i=1; $i<=5; $i++){
echo "Zeile $i <br>";
}
?>
</body>
</html>
Listing 6-7:
PHP6-7.php
Die for-Schleife besteht aus Kopf und Rumpf. Der Rumpf beinhaltet die Anweisungen
zwischen den geschweiften Klammern. Der Kopf besteht aus drei Teilen
 Startwert der Schleifenvariablen: Mit diesem Wert erfolgt der erste Durchlauf.
 Bedingung zur Wiederholung: Die Schleife wird solange wiederholt, wie diese Bedingung
wahr ergibt.
 Veränderung der Schleifenvariablen: Die Veränderung kann wie im Beispiel in Kurzform
oder ausführlich ($i = $i + 2) notiert werden.
Fehler können entstehen, wenn:
 Der Startwert der Schleifenvariablen die Prüfbedingung nicht erfüllt. In diesem Fall wird die
Schleife nicht durchlaufen. Sofern in ihr für den weiteren Programmablauf wichtige
Einstellungen vorgenommen werden, fehlen diese; im Programmablauf können Fehler
auftreten.
 Die Bedingung dauerhaft erfüllt ist (Endlosschleife), die Veränderung der Schleifenvariablen
also zu keinem ungültigen Wert führt. Dies ist in folgendem Beispiel des Schleifenkopfes der
Fall: for ($i=3; $i>2; $i++). Die Bedingung ergibt für jeden erzeugten Wert von
$i wahr.
Seite 22 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Übung 6.8: Schreiben
Sie ein Programm, dass mit Hilfe mehrerer for-Schleifen die nachfolgenden
Zeilen ausgibt. Die letzte Zahlenreihe benötigt eine zusätzliche if-Prüfung.
13
17
21
25
29
2
1.5
1
0.5
0
-0.5 -1
2000 3000 4000 5000 6000
Z5
Z7
Z9
Z11 Z13
ab1
ab2
ab3
c2
c3
c12
c13
c22
c23
13
17
21
33
37
41
45
Schleifen können sich auch innerhalb von Schleifen befinden. Man spricht dann von
geschachtelten Schleifen. Dies ermöglicht die Bearbeitung von mehrdimensionalen Strukturen,
die z.B. im Umgang mit Datenbankinhalten auftreten.
<html>
<body>
<?php
for ($i=1; $i<=5; $i++){
for ($j=1; $j<=3; $j++){
echo "Zeile $i / Spalte $j - ";
}
echo "<br>";
}
?>
</body>
</html>
Listing 6-8:
PHP6-8.php
Übung 6.9: Schreiben
Sie mit Hilfe von zwei geschachtelten for-Schleifen ein Programm, dass das
kleine Einmaleins ausgibt.
Schleifen werden häufig im Zusammenhang mit Tabellen eingesetzt. Gerade im Zusammenhang
mit Datenbanken wird dadurch die Ausgabe wesentlich lesbarer. Die einfache for-Schleife vom
Beginn dieses Kapitels ließe sich dann wie folgt darstellen. In dem folgenden Beispiel werden
Tabellenbeginn und -ende als HTML-Code im PHP-Bereich angegeben. Hierbei ist zu beachten,
dass die Zellausrichtung (align = 'right') innerhalb der Zeichenkette (also zwischen
doppelten Hochkommata / Anführungszeichen) in einfachen Hochkommata angegeben werden
muss, da andernfalls für PHP die Zeichenkette zu früh beendet wäre.
<html>
<body>
<table>
<?php
for ($i=1; $i<=5; $i++){
echo "<tr><td>Zeile</td><td align='right'>$i</td></tr>";
}
?>
</table>
</body>
</html>
Listing 6-9:
PHP6-9.php
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 23 von 54
Die geschachtelte Schleife könnte wie folgt in eine Tabelle ausgegeben werden:
<html>
<body>
<table>
<?php
for ($i=1; $i<=5; $i++){
echo "<tr>";
for ($j=1; $j<=3; $j++){
echo "<td align='right'>Zeile $i / Spalte $j</td>";
}
echo "</tr>";
}
?>
</table>
</body>
</html>
Listing 6-10:
PHP6-10.php
Übung 6.10: Geben
6.3.2
Sie das Einmaleins aus Übung 6.9 in eine Tabelle aus.
while-Schleife
Mit der while-Schleife lässt sich eine unbestimmte Anzahl von Wiederholungen erzeugen. Das
Ende der Wiederholungen wird durch eine Bedingung während der Schleifendurchläufe erreicht
und ist nicht vorhersehbar. while-Schleifen werden häufig bei Datenbankabfragen eingesetzt,
da die Anzahl der einzulesenden Elemente vorher meist nicht bekannt ist. Da die Bedingung in
der while-Schleife am Anfang geprüft wird, nennt man diese Art kopfgesteuert.
Im folgenden Beispiel sollen die "zufälligen" Würfelergebnisse eines Zufallsgenerators solange
addiert werden, bis der Würfel eine sechs zeigt. Auf die notwendigen mathematischen
Funktionen soll hier nur kurz eingegangen werden. Die Funktionen srand() initialisiert den
Zufallsgenerator, damit er tatsächlich zufällige Ergebnisse produziert. Die Funktionen rand()
erzeugt damit jeweils ein Würfelergebnis in den angegebenen Grenzen. Die Anzahl der Würfe
sind sowohl dem Entwickler also dem Benutzer unbekannt, daher kann keine for-Schleife
verwendet werden.
<html>
<body>
<?php
/* Initialisierung */
srand((double)microtime()*1000000);
$summe = 0;
$zaehler = 0;
$zufallszahl = 0;
while ($zufallszahl != 6){
$zaehler += 1;
$zufallszahl = rand(1,6);
//Würfel
$summe = $summe + $zufallszahl;
echo "Gewürfelt wurde $zufallszahl<br>";
}
echo "Insgesamt $zaehler Würfe, Gesamtsumme $summe<br>";
?>
</body>
</html>
Listing 6-11:
PHP6-11.php
Seite 24 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Neben dem Zufallsgenerator werden in der Initialisierung noch die Variablen $summe,
$zaehler und $zufallszahl auf 0 initialisiert. Die while-Schleife prüft in ihrem Kopf,
ob die Zufallszahl ungleich sechs ist. Dies ist zu Beginn der Fall, so dass der Schleifenkörper
durchlaufen wird. Als erstes wird der Zähler um eins hoch gezählt. In ihm findet sich also die
gesamte Zahl der bisherigen Würfel wieder. Nach der Erzeugung der Zufallszahl wird diese zu
der Gesamtsumme hinzu addiert. Danach wird die Zufallszahl ausgegeben. Nach dem Wurf einer
sechs wird die Schleife abgebrochen, das Programm gibt dann die gesamte Zahl der Würfe sowie
die gesamte Summe aus.
Zwei Spieler würfeln abwechselnd gegeneinander (Zufallsgenerator). Die Würfel
jedes Spielers werden addiert. Sobald einer der beiden Spieler eine Sechs wirft, ist das Spiel zu
Ende.
Übung 6.11:
Mithilfe der Anweisung break, die bereits aus der switch-case-Verzweigung bekannt ist,
kann eine Schleife vorzeitig beendet werden. Diese zusätzliche Möglichkeit einer
Schleifensteuerung kann ein Programm unter Umständen besser lesbar machen. Eine breakAnweisung innerhalb einer Schleife wird immer gemeinsam mit einer Bedingung auftreten, da der
vorzeitige Schleifenabbruch nur in einem Sonderfall erfolgen sollte.
Ähnlich der break-Anweisung kann die Anweisung continue dazu verwendet werden,
aufgrund einer Bedingung den Rest einer Schleife zu überspringen und unmittelbar mit dem
nächsten Schleifendurchlauf fortzusetzen.
Im Folgenden wird das obige Beispiel dahingehend erweitert, dass eine maximale Zahl von neun
Würfen gestattet ist, bevor ein Abbruch erfolgt. Dieser Abbruch erfolgt mit Hilfe der breakAnweisung.
<html>
<body>
<?php
/* Initialisierung */
srand((double)microtime()*1000000);
$summe = 0;
$zaehler = 0;
$zufallszahl = 0;
while ($zufallszahl != 6){
$zaehler += 1;
$zufallszahl = rand(1,6);
//Würfel
$summe = $summe + $zufallszahl;
echo "Gewürfelt wurde $zufallszahl<br>";
if ($zaehler >= 9) break;
//Sonderfall
}
echo "Insgesamt $zaehler Würfe, Gesamtsumme $summe<br>";
?>
</body>
</html>
Listing 6-12:
PHP6-12.php
Die Übung 6.11 soll wie folgt erweitert werden: Das Spiel ist beendet, wenn einer
der beiden Spieler 30 Punkte erreicht hat.
Übung 6.12:
Einführung in die Programmierung mit PHP und MySQL.doc
6.3.3
Seite 25 von 54
do-while-Schleife
Die do-while-Schleife verhält sich wie eine while-Schleife. Es gilt aber, dass sie mindestens
einmal durchlaufen wird, da die Bedingung für die Wiederholung erst am Ende geprüft wird.
Eine solche Schleife nennt man fußgesteuert. Die Syntax lautet:
do
{
[Anweisungen]
}
while (Bedingung);
6.3.4
foreach-Schleife
Die foreach-Schleife wird im Zusammenhang mit assoziativen Feldern6 verwendet. Sie
ermöglicht die Bearbeitung aller Elemente eines solches Feldes mit einer Schleife. Die Syntax
lautet:
foreach ([Feldausdruck])
{
[Anweisungen]
}
6
Zur Verwendung der foreach-Schleife siehe Kapitel 7.2
Seite 26 von 54
7
Einführung in die Programmierung mit PHP und MySQL.doc
Felder
Um eine größere Anzahl zusammengehöriger Daten zu speichern, sind einzelne Variablen
(jeweils mit einem eigenen Namen) ungeeignet. Zum einen müsste jede Variable über ihren
eigenen Namen angesprochen werden, zum anderen müsste eine ausreichend große Zahl von
Variablen vorgehalten werden, damit alle Daten abgespeichert werden könnten.
Feldvariablen (Arrays) sind hier weitaus flexibler und komfortabler. PHP unterstützt zwei Arten
von Feldvariablen:
 Numerisch indizierte Felder. Hier werden die einzelnen Variablen des Feldes über eine
laufende Nummer angesprochen.
 Assoziative Felder (auch Hash-Tabelle genannt). Jede Variable in dem assoziativen Feld wird
über eine eindeutige Bezeichnung angesprochen. Diese Form erhält ihre Bedeutung
insbesondere in mehrdimensionalen Feldern beim Einlesen von Datenbankinhalten.
Felder können eine oder mehrere Dimensionen haben:
 Ein eindimensionales Feld kann man sich einfach als eine Liste oder einen mathematischen
Vektor vorstellen. Beispiele wären eine Liste von Messwerten oder eine Zufallszahlenreihe.
 Ein zweidimensionales Feld kann man sich wie eine (Datenbank-)Tabelle vorstellen. In der
einen Dimension wären dann die Feldnamen (Attributnamen), in der anderen die Datensätze.
Zweidimensionale Felder können rein numerisch indiziert, rein assoziativ oder gemischt (dies
ist der häufigste Fall bei Datenbanktabellen) auftreten.
 Mehrdimensionale Felder können in reiner Form oder in beliebiger Mischform auftreten. Mit
steigender Zahl der Dimensionen wird allerdings die Modellvorstellung sowie die
Handhabung immer schwieriger.
7.1
Numerisch indizierte Felder
Als Beispiel für ein numerisch indiziertes Feld sollen hier die Temperaturen einer Messstation
dienen. Dabei sollen über eine Woche täglich die Temperaturen gemessen, abgespeichert und am
Ende ausgegeben werden.
<html>
<body>
<?php
$tp = array(17.5, 19.2, 21.8, 21.6, 17.5);
$tp[5] = 20.2;
$tp[] = 16.6;
for ($i=0; $i<=6; $i++){
echo „$tp[$i] <br>“;
}
?>
</body>
</html>
Listing 7-1:
PHP7-1.php
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 27 von 54
Das Programm zeigt drei Techniken zur Erzeugung bzw. Vergrößerung von Feldern:
 Mit Hilfe der Funktion array() wird die Variable $tp zu einem Feld mit hier fünf
Elementen. Diese Elemente werden automatisch durchnummeriert.
 Das erste Element in numerischen Feldern ist immer das Element 0.
 Felder können auch durch direkte Zuweisung einzelner Elemente erzeugt oder vergrößert
werden. Die Zuweisung $tp[5] = 20.2; erzeugt hier eine neues (sechstes) Element und
weist diesem den Wert 20.2 zu. Eine Zuweisung an ein schon vorhandenes Element
überschreibt den alten Wert.
 Ein leerer Schlüssel zwischen den eckigen Klammern erzeugt das nächste Element. Der
Vorteil dieser Schreibweise ist, dass man die bisherige Anzahl der Elemente nicht wissen
muss und nicht aus Versehen ein vorhandenes Element überschreibt.
 Ein einzelnes Feld wird angesprochen, indem man nach dem Namen des Feldes die laufende
Nummer (Index) des Elementes in eckigen Klammern angibt. Dies geschieht im Beispiel
durch eine for-Schleife.
Es sollen die Vornamen und das Alter von sechs Personen gespeichert werden. Das
erste Feld soll dabei die Namen, das zweite das Alter enthalten. Die Elemente der beiden Felder
sollen paarweise untereinander als Tabelle ausgegeben werden.
Übung 7.1:
7.2
Assoziative Felder
Die Temperaturwerte sollen nun einem assoziativen Feld zugeordnet werden. Dabei sollen die
Werte jeweils einem Wochentag zugeordnet sein.
<html>
<body>
<?php
$tp = array ("Montag"=>17.5, "Dienstag"=>19.2, "Mittwoch"=>21.8);
$tp["Donnerstag"] = 21.6;
$tp["Freitag"] = 17.5;
$tp["Samstag"] = 20.2;
$tp["Sonntag"] = 16.6;
// Ein bestimmtes Element ausgeben
echo $tp["Montag"] . "<br>";
// Alle Elemente in eine Tabelle ausgeben
// Tabellenkopf
echo "<table>";
echo "<tr><td><b>Wochentag</b></td>";
echo "<td><b>Temperatur</b></td></tr>";
// Namen und Werte ausgeben
foreach ($tp as $name=>$wert){
echo "<tr><td>$name</td><td align='right'>$wert</td></tr>";
}
echo "</table>";
Seite 28 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
//Nun die Durchschnittstemperatur
$summe = 0;
foreach ($tp as $wert){
$summe = $summe + $wert;
}
$durchschnitt = $summe / 7;
echo "<br>Durchschnitttemperatur: $durchschnitt";
?>
</body>
</html>
Listing 7-2:
PHP7-2.php
Die Verwendung assoziativer Felder kann zunächst etwas unübersichtlich wirken. Die direkte
Bezeichnung der Elemente kann aber durchaus Vorteile bieten.
In diesem Beispiel sind zwei Techniken zur Felderzeugung dargestellt:
 Die Funktion array() erzeugt ein Feld mit drei Elementen Jedes Element hat eine eindeutige
Schlüsselbezeichnung (Key) und einen zugehörigen Wert (Value). Der Key muss dabei
zwischen doppelten Hochkommata geschrieben werden.
 Felder können auch durch Zuweisung einzelner Elemente erzeugt oder vergrößert werden.
Dabei muss der Key innerhalb der eckigen Klammern ebenfalls in doppelten Hochkommata
stehen.
 Da der Key immer in doppelten Hochkommata stehen muss, ist die Ausgabe des einzelnen
Elements mit folgendem Zeilenumbruch nur durch eine Stringzusammensetzung möglich.
Alle folgenden Vorgehensweisen führen zu einem Fehler oder einer falschen Ausgabe:
o echo "$tp["Montag"]<br>"; beendet die Zeichenkette zu früh.
o echo "$tp['Montag']<br>"; erkennt den Index nicht.
o echo '$tp["Montag"]<br>'; liefert nur den Namen des Feldelements,
nicht seinen Wert.
 In der ersten foreach-Schleife wird bei jedem Schleifendurchlauf ein Key-Value-Paar
bereitgestellt. Die Bedeutung des Zeichens "=>" ist dabei dieselbe wie bei der Zuweisung. Es
werden somit sowohl der Name als auch der Wert des aktuellen Elements bereitgestellt.
 Ohne das Zuordnungszeichen wird in der zweiten foreach-Schleife nur der Wert des
Elements bereitgestellt. Dieser Wert wird hier zur Berechnung genutzt.
Die Aufgabe der Übung 7.1 soll mit assoziativen Feldern gelöst werden. Dabei sollen
die Vornamen die Keys, das Alter die Werte darstellen.
Übung 7.2:
Erweitern Sie Übung 7.2, indem Sie ein zweidimensionales Feld erzeugen. Dazu soll
zunächst ein eindimensionales assoziatives Feld $personen mit den Keys "Vorname" und "Alter"
erzeugt werden. Dieses Feld weisen Sie dann jeweils einem neuen Feld $freunde als numerisch
indiziertes Feldelement zu, nachdem Sie mehrmals neue Werte eingegeben haben. Die
Vorgehensweise dabei ist: $freunde[] = $personen; Experimentieren Sie mit der Ausgabe des
Gesamtfeldes in geschachtelten foreach-Schleifen.
Übung 7.3:
Einführung in die Programmierung mit PHP und MySQL.doc
8
Seite 29 von 54
Datenbankverbindung
PHP bietet komfortable Schnittstellen zu einer Reihe von Datenbanken. An dieser Stelle soll
ausschließlich die Schnittstelle zu MySQL angesprochen werden. Dabei wird davon ausgegangen,
dass die Erzeugung der Datenbank und der Strukturentwurf vorher mit einem der Hilfstools der
Datenbank durchgeführt wurden.
8.1
Der erste Kontakt
Das folgende Programm zeigt alle Datensätze der Tabelle personen aus der Datenbank
phpuebungen an.
(Hinweis: Die hier verwendete Datenbank kann von den Seiten der Jobelmann-Schule
heruntergeladen werden. Aufruf: www.jobelmann-schule.de Reiter: Sonstiges - Dokumente.
Dort dem folgenden Pfad folgen:
 Informationen zu einzelnen Schulfächern  Informationstechnik/-verarbeitung / Informatik
 Programmierung  HTML / PHP)
<html>
<body>
<?php
/* Verbindung zu MySQL aufnehmen */
mysql_connect ("", "phptest", "phptest");
/* Datenbank auswählen */
mysql_select_db("phpuebungen");
/* SQL-Abfrage ausführen */
$res = mysql_query ("select * from personen");
/* Anzahl der Datensätze ermitteln */
$num = mysql_num_rows ($res);
echo "$num Datensätze gefunden<br>";
/* Datensätze auslesen */
while ($dsatz = mysql_fetch_array ($res)){
echo $dsatz["name"] . ", ";
echo $dsatz["vorname"] . ", ";
echo $dsatz["personalnummer"] . ", ";
echo $dsatz["gehalt"] . ", ";
echo $dsatz["geburtstag"] . "<br>";
}
/* Datenbank schließen */
mysql_close();
?>
</body>
</html>
Listing 8-1:
PHP8-1.php
Seite 30 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Erläuterung des Programms:
 Die Funktion mysql_connect() öffnet eine Verbindung zum Datenbankserver. Es
können drei Parameter angegeben werden: Hostname, Benutzername, Kennwort.
Hier ist die Standardeinstellung von XAMPP für den Host gewählt, also localhost und
der Benutzer "phptest" mit dem Kennwort "phptest"..
 Mit der Funktion mysql_select_db() wird die Datenbank ausgewählt, mit der
gearbeitet wird. Dies ist wichtig, da MySQL mehrere Datenbanken gleichzeitig enthalten
kann.
 Die Funktion mysql_query() führt eine SELECT-Anfrage in der aktuellen Datenbank
aus und liefert das Ergebnis in einem assoziativen Feld zurück. Der Parameter der Funktion
enthält dabei die SQL-Abfrage in doppelten Hochkommata, allerdings ohne schließendes
Semikolon. Das zweidimensionale Feld enthält die Attributwerte als Spalten
(mysql_num_fields) und die Datensätze als Zeilen (mysql_num_rows). Wenn der
letztgenannte Wert 0 ergibt, hat die Abfrage kein Ergebnis zurückgeliefert, die
Ergebniskennung ist aber wahr. Nur wenn die SQL-Abfrage syntaktisch falsch oder die
Kommunikation mit dem MySQL-Server gestört war, liefert die Funktion als Ergebnis
falsch zurück.
 Das Ergebnis der Abfrage wird in einer Variablen ($res) als so genannte Ergebniskennung
abgelegt. Mit ihrer Hilfe lassen sich die einzelnen Komponenten des Ergebnisses ermitteln.
Bei mehreren Abfragen sollte für jedes Ergebnis eine eigene Variable zur Speicherung der
Ergebniskennung verwendet werden.
 Die Funktion mysql_num_rows() liefert die Anzahl der Datensätze der als Parameter
übergebenen Ergebnismenge zurück.
 Die Funktion mysql_fetch_array() liefert einen Datensatz der Ergebniskennung in
einem assoziativen Feld zurück. Dabei stellt der Datenbank-Feldname (bzw. der angegebene
Aliasname) den Schlüssel des Feldes dar. Nach dem Aufruf der Funktion wird der
Datensatzzeiger automatisch auf den nächsten Datensatz der Ergebnismenge weitergesetzt.
 Wenn der Datensatzzeiger am Ende der Ergebnismenge steht, ergibt der nächste Aufruf von
mysql_fetch_array() den Wert falsch. Dadurch wird die while-Schleife beendet.
 Das Ergebnis der Abfrage lässt sich durch weitere Funktionen ermitteln, die hier kurz mit
ihren Unterschieden dargestellt werden sollen:
o $dfeld = mysql_result ($res, $row, $col); liefert den
direkten Zugriff auf jedes Element, wobei die Zeilen- und Spaltennummer als
zusätzliche Parameter (beginnend mit 0!) übergeben werden müssen. Statt der
Spaltennummer kann auch der Spaltenname angegeben werden. Diese Form stellt
eine recht langsame Art des Zugriffs dar.
o $dsatz = mysql_fetch_row ($res); liefert den Datensatz als
numerisches Feld zurück. Der Zugriff erfolgt über $dsatz[$n].
o $dsatz = mysql_fetch_array ($res); liefert den Datensatz als
assoziatives Feld zurück. Der Zugriff kann über die Spaltennummer oder den
Spaltennamen erfolgen. Der Spaltenname muss dabei in korrekter Groß- und
Kleinschreibung angegeben werden.
o $dsatz = mysql_fetch_assoc ($res); liefert ebenfalls ein
assoziatives Feld, allerdings ist hier ein Zugriff über die Spaltennummer nicht
zulässig.
o $dsatz = mysql_fetch_object ($res); liefert den Datensatz als
Objekt zurück.
 Nach Ablauf des PHP-Programms wird die Verbindung zur Datenbank automatisch
geschlossen. Dennoch ist es guter Programmierstil, dies explizit mit mysql_close() zu
tun.
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 31 von 54
Erstellen Sie in MySQL eine Datenbank und lassen Sie sich die Werte aller Tabellen
durch ein PHP-Programm anzeigen.
Übung 8.1:
8.2
Datensätze auswählen
PHP bietet alle Möglichkeiten zur Auswahl und Manipulation von Datensätzen durch SQLAnweisungen. Dabei sind alle Varianten der Auswahl mit WHERE, Vergleichsoperatoren,
logischen Operatoren, LIKE-Operator, ORDER BY, GROUP BY usw. möglich. Zu beachten ist
dabei allerdings eine eventuelle Schachtelung von PHP-Stringausdrücken und eingelagerten SQLStrings. Hierbei sind die PHP-Ausdrücke in Anführungszeichen ("), die SQL-Werte in
Hochkommata (') einzuschließen.
Das folgende Beispiel wählt die Namen und das Gehalt aller Personen der Übungsdatenbank aus,
die 1990 oder später geboren sind und sortiert diese absteigend nach Gehalt:
<html>
<body>
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT name, vorname, gehalt FROM personen";
$abfrage .= " WHERE YEAR (geburtstag) >= '1990'";
$abfrage .= " ORDER BY gehalt DESC";
$res = mysql_query ($abfrage);
while ($dsatz = mysql_fetch_array ($res)){
echo $dsatz["name"] . ", " . $dsatz["vorname"] . ", "
. $dsatz["gehalt"] . "<br>";
}
?>
</body>
</html>
Listing 8-2:
PHP8-2.php
Die SQL-Anweisung wurde aus Gründen der Übersichtlichkeit in mehreren Schritten
zusammengesetzt und in einer PHP-Variablen ($abfrage) gespeichert. Besonders zu beachten
(und fehlerträchtig) sind die Leerzeichen zwischen den Anweisungen (hier vor WHERE und
ORDER BY), da fehlende Leerzeichen von SQL mit einer Fehlermeldung quittiert werden. Die
Jahresangabe zum Abgleich des Geburtstages steht in einfachen Hochkommata ('1990').
SQL-Anweisungen können durch ihre Länge, eingebaute PHP-Variable oder Feldnamen schnell
unübersichtlich und damit zur größten Fehlerquelle werden. Zur Prüfung einer fehlerfreien
Anweisung kann man sich die Zeichenkette zunächst ausgeben lassen (echo $abfrage;).
Zeigen Sie aus der obigen Tabelle alle Daten der Personen an, deren Nachnamen mit
"M" beginnt.
Übung 8.2:
Zeigen Sie aus der obigen Tabelle den Vornamen, Nachnamen und Geburtstag
aufsteigend nach dem Alter von allen Personen an, die mehr als € 3.000,00 verdienen.
Übung 8.3:
Seite 32 von 54
8.3
Einführung in die Programmierung mit PHP und MySQL.doc
Ausgabe in eine HTML-Tabelle
Bisher werden zwar alle Daten angezeigt, die Darstellung ist aber noch sehr unübersichtlich. Die
Lesbarkeit der Ergebnisse ist wesentlich besser, wenn die Daten in einer Tabelle ausgegeben
werden. Dazu müssen nur die HTML-Befehle zur Erzeugung einer Tabelle an geeigneter Stelle in
das PHP-Programm integriert werden. Das folgende Programm gibt die Daten des letzten
Kapitels in Tabellenform aus.
<html>
<body>
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT name, vorname, gehalt FROM personen";
$abfrage .= " WHERE YEAR (geburtstag) >= '1990'";
$abfrage .= " ORDER BY gehalt DESC";
$res = mysql_query ($abfrage);
// Beginn der Tabelle
echo "<table border = '1'>";
// Tabellenüberschrift
echo "<tr> <td>Name</td> <td>Vorname</td> <td>Gehalt></td> </tr>";
while ($dsatz = mysql_fetch_array ($res)){
// Ausgabe der Daten in die Tabellenfelder
echo "<tr>";
// neue Tabellenzeile
echo "<td>" . $dsatz["name"] . "</td>";
// erste Spalte
echo "<td>" . $dsatz["vorname"] . "</td>"; // zweite Spalte
echo "<td>" . $dsatz["gehalt"] . "</td>";
// dritte Spalte
echo "</tr>";
// Ende der Zeile
}
// Tabellenende (nicht vergessen!)
echo "</table>";
?>
</body>
</html>
Listing 8-3:
PHP8-3.php
Innerhalb der while-Schleife wird jeweils ein Datensatz in eine Tabellenzeile ausgegeben. Somit
müssen auch die Tags <tr> und </tr> innerhalb der Schleife angeordnet werden. Die Tabelle
selbst wird nur einmal erzeugt (vor der Schleife) ebenso, wie die Überschrift nur einmal in einer
eigenen Tabellenzeile ausgegeben wird. Am Ende muss die Tabelle noch (nach dem vollständigen
Durchlauf der Schleife) geschlossen werden.
Übung 8.4: Geben
Sie die Daten aus Übung 8.2 in einer Tabelle aus.
Übung 8.5: Geben
Sie die Daten aus Übung 8.3 in einer Tabelle aus.
Einführung in die Programmierung mit PHP und MySQL.doc
8.4
Seite 33 von 54
Auswahl von Daten in einem Suchformular
Normalerweise ist es nicht ausreichend, wenn der Programmentwickler statische Abfragen
vorgibt. Sinn einer Datenbank ist es meist, dass der Benutzer eine Auswahl treffen kann, auf
deren Grundlage ihm dann Daten angezeigt werden. Dies wird durch Eingabe oder Auswahl von
Werten in Formularen ermöglicht.
Der Ablauf einer typischen Datenbankanwendung stellt sich wie folgt dar:
 Der Benutzer trägt Daten in ein Eingabefeld ein oder wählt aus einem Auswahlfeld eingaben
aus. Mit dem Klick auf den Sende-Button werden diese Daten an den Webserver übertragen.
 Auf dem Webserver werden die gesendeten Daten von einem PHP-Programm ausgewertet,
in eine SQL-Anweisung eingebettet und an den Datenbankserver gesendet.
 Der Datenbankserver führt die SQL-Anweisung aus und liefert die Ergebnisdaten zurück an
den Webserver.
 Das PHP-Programm verarbeitet die zurück gelieferten Daten und erstellt für den Benutzer
eine entsprechende HTML-Seite.
Während des gesamten Ablaufs ist es für den Benutzer nicht erkennbar, welche Programme für
ihn im Hintergrund tätig sind. Auf seine Anfrage wird ihm eine nach außen "normale" HTMLSeite zurückgeliefert, ohne dass er Kenntnisse über Programmsprachen oder Datenbanken
besitzen muss.
Das folgende Beispiel baut auf den letzten Beispielabfragen auf. Nur soll das Geburtsjahr nicht
mehr fest vorgegeben, sondern vom Benutzer eingegeben werden. Dazu erzeugen wir eine
HTML-Seite zur Eingabe und ein PHP-Programm zur Ausgabe. Zunächst das Formular. Um uns
eine Fehlerprüfung zu ersparen und unsinnige Eingaben zu vermeiden wollen wir hier zunächst
nur eine Auswahl aus einer vorgegebenen Liste zulassen:
<html>
<body>
Bitte w&auml;hlen Sie das Start-Geburtsjahr aus
<form action = "PHP8-4.php" method = "post">
<select name = "alter" size = "1">
<option>1970</option>
<option>1975</option>
<option>1980</option>
<option>1985</option>
<option>1990</option>
<option>1995</option>
<option>2000</option>
</select> <br>
<input type = "submit">
<input type = "reset">
</form>
</body>
</html>
Listing 8-4:
PHP8-4.htm
Innerhalb des Formulars kann in einer Dropdown-Liste schrittweise eine Jahreszahl ausgewählt
werden. Die einzelnen Werte werden innerhalb des select-Containers über das option-Tag
angegeben. Die Höhe des select-Feldes (size = "1") entscheidet darüber, wie viele Werte
im geschlossenen Feld angezeigt werden. Werte größer als eins führen also zu einer Auswahlliste.
Seite 34 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Der ausgewählte Wert steht dem aufgerufenen PHP-Programm nach dem Absenden zur
Verfügung. Die Auswertung sieht dann wie folgt aus:
<html>
<body>
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT name, vorname, gehalt FROM personen";
$abfrage .= " WHERE YEAR (geburtstag) >= " . $_POST["alter"];
$abfrage .= " ORDER BY gehalt DESC";
$res = mysql_query ($abfrage);
$num = mysql_num_rows ($res);
if ($num == 0) echo "Keine Datensätze gefunden";
echo "<table border = '1'>";
echo "<tr> <td>Name</td> <td>Vorname</td> <td>Gehalt></td> </tr>";
while ($dsatz = mysql_fetch_array ($res)){
// Ausgabe der Daten in die Tabellenfelder
echo "<tr>";
echo "<td>" . $dsatz["name"] . "</td>";
echo "<td>" . $dsatz["vorname"] . "</td>";
echo "<td>" . $dsatz["gehalt"] . "</td>";
echo "</tr>";
}
echo "</table>";
?>
</body>
</html>
Listing 8-5:
PHP8-4.php
Es ist also zu erkennen, dass der feste Jahreswert nun durch den Inhalt der Variablen
$_POST["alter"] ersetzt wurde. Die Variable wurde also mit dem in select festgelegten
Namen (name =) übergeben. Dieser darf hier in Anführungszeichen stehen, da er nicht
innerhalb eines PHP-Strings verwendet wird!
Hinzugekommen sind hier die Ermittlung der Anzahl zurück gelieferter Datensätze und die
Ausgabe einer Meldung, wenn diese Null beträgt. Eine solche Vorgehensweise ist anzuraten, da
der Benutzer ansonsten nur einen leeren Bildschirm zurückbekommen würde (Die whileSchleife wird schon vor dem ersten Durchlauf beendet  kopfgesteuerte Schleife).
Im folgenden Beispiel sollen die Daten aller Personen ausgegeben werden, deren
Anfangsbuchstaben des Nachnamens mit der Eingabe übereinstimmen.
<html>
<body>
Auswahl der Personendaten f&uuml;r Nachnamen mit folgendem Anfang:
<form action = "PHP8-5.php" method = "post">
<input type = "text" name = "anfang"> <br>
<input type = "submit">
<input type = "reset">
</form>
</body>
</html>
Listing 8-6:
PHP8-5.htm
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 35 von 54
Sollen Daten auf der Grundlage von Textteilen ausgegeben werden, so ist besonders auf die
Verwendung der Hochkommata zu achten. Der Operator LIKE und die Platzhalter können wie
gewohnt verwendet werden.
<html>
<body>
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT name, vorname, gehalt FROM personen";
$abfrage .= " WHERE name LIKE '" . $_POST["anfang"] . "%'";
$res = mysql_query ($abfrage);
$num = mysql_num_rows ($res);
if ($num == 0) echo "Keine Datensätze gefunden";
echo "<table border = '1'>";
echo "<tr> <td>Name</td> <td>Vorname</td> <td>Gehalt></td> </tr>";
while ($dsatz = mysql_fetch_array ($res)){
// Ausgabe der Daten in die Tabellenfelder
echo "<tr>";
echo "<td>" . $dsatz["name"] . "</td>";
echo "<td>" . $dsatz["vorname"] . "</td>";
echo "<td>" . $dsatz["gehalt"] . "</td>";
echo "</tr>";
}
echo "</table>";
?>
</body>
</html>
Listing 8-7:
PHP8-5.php
Wie zu erkennen ist, muss die Eingabe für den LIKE-Operator in Hochkommata eingeschlossen
werden. Das beginnende Hochkomma steht in der ersten Teilkette hinter LIKE nach einem
Leerzeichen unmittelbar vor den Anführungszeichen, das schließende hinter dem Platzhalter (%).
Ändern Sie das Beispielprogramm PHP8-4.htm so ab, dass die Auswahl über RadioButtons erfolgt. Zur Definition von Radio-Buttons siehe http://de.selfhtml.org.
Vergeben Sie den Radio-Buttons einfache Werte (1, 2, ...) und führen Sie die Prüfung auf den
ausgewählten Wert im auswertenden PHP-Programm mit Hilfe von switch durch.
Übung 8.6:
Fügen Sie den Programmen aus Übung 8.6 noch eine Checkbox hinzu, mit der die
Ausgabe nach Gehalt aufsteigend bzw. absteigend sortiert ausgegeben wird.
Übung 8.7:
8.5
Exkurs: Rekursiver Aufruf der gleichen Datei
Bisher werden das Formular und das PHP-Programm in getrennten Dateien gespeichert. Der
Benutzer bekommt die HTML-Seite mit dem Formular vorgelegt, trifft seine Auswahl bzw. tätigt
seine Eingaben, sendet es ab und es wird ihm eine durch das PHP-Programm generierte Seite
zurückgesendet.
Seite 36 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Gerade (aber nicht nur) in Datenbankaufgaben möchte aber ein Benutzer nach der Ausgabe
häufig eine veränderte Abfrage starten. Dazu müsste er bei der jetzigen Vorgehensweise erst
wieder die HTML-Seite laden.
Günstiger wäre es also, wenn das Formular Teil des PHP-Programms wäre und dieses sich
immer wieder selbst aufrufen könnte. Das Programm würde sich somit auch die Daten selbst
zusenden. Dieses Verfahren wird im nächsten Beispiel vorgestellt:
<html>
<body>
<?php
// Prüfung, ob Daten existieren
if (isset ($_POST["gesendet"])){
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT name, vorname, gehalt FROM personen";
$abfrage .= " WHERE name LIKE '" . $_POST["anfang"] . "%'";
$res = mysql_query ($abfrage);
$num = mysql_num_rows ($res);
if ($num == 0) echo "Keine Datensätze gefunden";
echo "<table border = '1'>";
echo "<tr> <td>Name</td> <td>Vorname</td> <td>Gehalt</td> </tr>";
while ($dsatz = mysql_fetch_array ($res)){
// Ausgabe der Daten in die Tabellenfelder
echo "<tr>";
echo "<td>" . $dsatz["name"] . "</td>";
echo "<td>" . $dsatz["vorname"] . "</td>";
echo "<td>" . $dsatz["gehalt"] . "</td>";
echo "</tr>";
}
echo "</table>";
}
// Ende der Datenausgabe
?>
// Formulareingabe
Auswahl der Personendaten f&uuml;r Nachnamen mit folgendem Anfang:
<form action = "PHP8-6.php" method = "post">
<input type = "text" name = "anfang"> <br>
<input type = "submit" name = "gesendet">
<input type = "reset">
</form>
</body>
</html>
Listing 8-8:
PHP8-6.php
Der Trick liegt in der Abfrage if (isset ($_POST["gesendet"])), die prüft, ob die
angegebene Parametervariable existiert. Da beim ersten Aufruf noch keine POST-Daten
übertragen wurden, ist dies also nicht der Fall. Somit wird auch keine Ausgabe erzeugt. Erst wenn
sich die Datei selbst aufruft (nach dem Klicken auf den Senden-Button), ist die Bedingung erfüllt
und eine Ausgabe erfolgt, und zwar auch, wenn nichts eingegeben wurde, da die abgefragte
Parametervariable der Sendebutton selbst ist.
Übung 8.8:
aufrufen.
Verändern Sie Übung 8.6 und Übung 8.7 so, dass sie sich in einer Datei selbst
Einführung in die Programmierung mit PHP und MySQL.doc
8.6
Seite 37 von 54
Datensätze erzeugen
In vielen Fällen soll es bestimmten Benutzern auch gestattet sein, neue Datensätze einzugeben.
Die Berechtigung dazu muss über den Benutzernamen auf dem Datenbankserver vorher erteilt
worden sein. Im Folgenden wird davon ausgegangen, dass der Benutzer über alle notwendigen
Rechte auf dem Datenbankserver verfügt. Das nachfolgende Beispiel zeigt eine Eingabeseite, die
sich selbst aufruft, also das rekursive Konzept des letzten Abschnittes aufgreift.
<html>
<head>
<?php
if (isset ($_POST["gesendet"])){
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "INSERT personen ";
$abfrage .= "(name, vorname, geburtstag, gehalt) values ";
$abfrage .= "('" . $_POST["fname"] . "', ";
$abfrage .= "'" . $_POST["fvorname"] . "', ";
$abfrage .= "'" . $_POST["fgebdat"] . "', ";
$abfrage .= "'" . $_POST["fgehalt"] . "')";
// Aktionsabfrage – kein Rückgabewert
mysql_query ($abfrage);
// Ermittlung der Anzahl betroffener Datensätze
$num = mysql_affected_rows ();
// Unterscheidung nur zwischen 0 und 1
if ($num > 0){
echo "<p>Es wurde 1 Datensatz hinzugefügt</p>";
}else{
echo "<p>Ein Fehler ist aufgetreten.<br>";
echo "Es wurde kein Datensatz hinzugefügt</p>";
}
}
?>
</head>
<body>
<p>Datensatzeingabe</p>
<form action = "PHP8-7.php" method = "post">
<input type = "text" name = "fname"> Nachname<br>
<input type = "text" name = "fvorname"> Vorname<br>
<input type = "text" name = "fgebdat"> Geburtstag (JJJJ-MM-TT)<br>
<input type = "text" name = "fgehalt"> Gehalt (Dezimalpunkt!)<br>
<input type = "submit" name = "gesendet">
<input type = "reset">
</form>
</body>
</html>
Listing 8-9:
PHP8-7.php
Zunächst wird wieder geprüft, ob der Submit-Button seinen Namen übertragen hat, es sich also
um einen Folgeaufruf handelt. Ist dies der Fall, so wird versucht, die eingegebenen Daten an die
Datenbank zu übertragen und eine Meldung über den Erfolg oder Misserfolg auszugeben. Die
Entscheidung darüber wird auf Grund der Funktion mysql_affected_rows getroffen, die
zurückmeldet, wie viele Datensätze (Reihen) von der letzten Aktionsabfrage betroffen waren.
Übertragen werden hier nur die eigentlichen Daten. Die fünfte Angabe (Personalnummer) wird
automatisch erzeugt, da dieses Attribut als Autowert definiert ist.
Das Beispiel zeigt außerdem, dass der gesamte PHP-Code auch im head-Bereich der html-Seite
angeordnet werden kann.
Seite 38 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Verändern Sie das Beispielprogramm PHP8-7.php so, dass nach der (Erfolgs-)
Meldung die gesamten Daten übersichtlich in einer Tabelle ausgegeben werden. Die Tabelle
vergrößert sich also nach jedem Neueintrag.
Übung 8.9:
8.7
Datensätze ändern
An dieser Stelle soll nur auf das gezielte Ändern einzelner Datensätze eingegangen werden.
Globale Änderungen wie z.B. die pauschale Erhöhung der Gehälter um einen bestimmten
Prozentsatz können aber analog zu der dargestellten Vorgehensweise (meist mit deutlich weniger
Aufwand) durchgeführt werden.
Um einen Datensatz gezielt ändern zu können, muss er zunächst eindeutig identifiziert werden.
Eine für den Anwender sehr komfortable Vorgehensweise hierzu zeigen die folgenden
Beispielprogramme.
 Zunächst werden dem Benutzer alle Datensätze angezeigt. Dabei ist jeder Datensatz mit
einem Radiobutton versehen, den der Benutzer zur Auswahl eines Datensatzes anklicken
kann. Um unmittelbar eine eindeutige Beziehung zum Datensatz herzustellen, wird schon bei
der Erzeugung der Ausgabetabelle der Wert jedes Radiobuttons auf den Wert des
Primärschlüsselfeldes (hier. Personalnummer) gesetzt. So kann im aufgerufenen Programm
unmittelbar auf den betroffenen Datensatz zugegriffen werden. (PHP8-8.php)
 Im nächsten Schritt wird der zu ändernde Datensatz in einem Formular angezeigt, wo der
Benutzer seine Änderungen vornehmen kann. (PHP8-9.php)
 Nach dem Absenden werden die geänderten Daten in die Datenbank eingetragen und eine
entsprechende Meldung ausgegeben. Danach hat der Benutzer die Möglichkeit, wieder zum
ersten Formular zurückzukehren. (PHP8-10.php)
Hier nun der Reihe nach die PHP-Dateien, zunächst die Seite zur Auswahl des Datensatzes:
<html>
<body>
<p>W&auml;hlen Sie den zu &auml;ndernden Datensatz aus:</p>
<form action = "PHP8-9.php" method = "post">
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$res = mysql_query ("SELECT * FROM personen");
// Beginn der Tabelle
echo "<table border = '1'>";
// Tabellenüberschrift
echo "<tr> <td>&nbsp;</td>"; //geschütztes Leerzeichen (Auswahl)
echo "<td>Name</td> <td>Vorname</td>";
echo "<td>Geburtstag</td> <td>Gehalt></td> </tr>";
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 39 von 54
while ($dsatz = mysql_fetch_array ($res)){
// Ausgabe der Daten in die Tabellenfelder
echo "<tr>";
echo "<td><input type = 'radio' name = 'auswahl'";
echo " value = '" . $dsatz["personalnummer"] . "'></td>";
echo "<td>" . $dsatz["name"] . "</td>";
echo "<td>" . $dsatz["vorname"] . "</td>";
echo "<td>" . $dsatz["geburtstag"] . "</td>";
echo "<td>" . $dsatz["gehalt"] . "</td>";
echo "</tr>";
}
echo "</table>";
?>
<!-- Sendebutton -->
<p><input type = "submit" value = "Datensatz &auml;ndern"></p>
</form>
</body>
</html>
Listing 8-10:
PHP8-8.php
Die Personalnummer des ausgewählten Datensatzes befindet sich in der Variablen auswahl
und wird an das folgende Skript übertragen. Dort kann nun gezielt die Änderung vorgenommen
werden:
<html>
<body>
<?php
if (isset ($_POST["auswahl"])){
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "SELECT * FROM personen WHERE ";
$abfrage .= "personalnummer = " . $_POST["auswahl"];
$res = mysql_query ($abfrage);
$dsatz = mysql_fetch_array ($res);
// nur 1 Datensatz!
echo "<p>Daten zur Änderung:</p>";
echo "<form action = 'PHP8-10.php' method = 'post'>";
echo "<p><input type = 'text' name ='nn' value = '";
echo $dsatz["name"] . "'> Nachname</p>";
echo "<p><input type = 'text' name ='vn' value = '";
echo $dsatz["vorname"] . "'> Vorname</p>";
echo "<p><input type = 'text' name ='gt' value = '";
echo $dsatz["geburtstag"] . "'> Geburtstag</p>";
echo "<p><input type = 'text' name ='ge' value = '";
echo $dsatz["gehalt"] . "'> Gehalt</p>";
echo "<input type = 'hidden' name ='pn' value = '";
echo $dsatz["personalnummer"]."'>";
echo "<input type = 'submit' value = 'Änderungen speichern'>";
echo "<input type = 'reset'>";
echo "</form>";
}else{
echo "<p>Es wurde kein Datensatz ausgewählt</p>";
echo "<p>Zurück zur <a href = 'PHP8-8.php'>Auswahl</a></p>";
}
?>
</body>
</html>
Listing 8-11:
PHP8-9.php
Seite 40 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Wenn ein Datensatz ausgewählt war, werden dessen Daten eingelesen und in einem Formular zur
Änderung bereitgestellt. Um die Änderungen im nächsten PHP-Skript wieder richtig speichern zu
können, wird der Primärschlüssel (hier: personalnummer) in einem versteckten Textfeld
(type = "hidden") gespeichert und von dort an das nächste Skript übertragen. Sofern
kein Datensatz ausgewählt war, wird nur eine Meldung ausgegeben und über einen Hyperlink der
Rücksprung zur Auswahlseite ermöglicht.
Das Eintragen der Änderungen erfolgt nunmehr in der letzten PHP-Datei:
<html>
<body>
<?php
mysql_connect ("", "phptest", "phptest");
mysql_select_db("phpuebungen");
$abfrage = "UPDATE personen SET ";
$abfrage .= "name = '" . $_POST["nn"] . "', ";
$abfrage .= "vorname = '" . $_POST["vn"] . "', ";
$abfrage .= "geburtstag = '" . $_POST["gt"] . "', ";
$abfrage .= "gehalt = '" . $_POST["ge"] . "' ";
$abfrage .= "WHERE personalnummer = " . $_POST["pn"];
mysql_query ($abfrage);
$num = mysql_affected_rows();
if ($num > 0)
echo "Der Datensatz wurde geändert";
else
echo "Die Datensatzänderung ist fehlgeschlagen";
?>
<p>Zur&uuml;ck zur <a href = "PHP8-8.php">Auswahl</a></p>
</body>
</html>
Listing 8-12:
PHP8-10.php
Die Änderung wird mit der SQL-Anweisung UPDATE durchgeführt, wobei die Auswahl des zu
ändernden Datensatzes analog zur SELECT-Anweisung mit der WHERE-Klausel durchgeführt
wird. Anschließend hat der Benutzer die Möglichkeit, zur Anzeigeseite zurückzukehren und
weitere Änderungen durchzuführen.
Verbinden Sie die Funktion des ersten PHP-Skriptes (PHP8-8.php: Anzeigen aller
Datensätze) mit der des letzten (PHP8-10.php: Speichern der Änderungen und Erfolgsmeldung).
Ein Rücksprung ist dann nicht mehr notwendig, da sich der Benutzer unmittelbar auf der
richtigen Seite befindet. Denken Sie daran, dass notwendigerweise geprüft werden muss, ob die
Seite mit geänderten Daten angesprungen wird (Fall 1 der zweiseitigen Auswahl in PHP8-9.php)
oder ob der Rücksprung erfolgt, weil kein Datensatz ausgewählt war!
Übung 8.10:
Einführung in die Programmierung mit PHP und MySQL.doc
9
Seite 41 von 54
Zugriffsautorisierung
Wir alle wissen, dass HTTP das Webprotokoll ist, also das Protokoll, mit dem Browser und
Webserver kommunizieren. Es ist sicherlich auch bekannt, dass HTTP ein statusloses Protokoll
ist. Es ist ein einfaches Anfrage/Antwort-Protokoll. Der Browser macht eine Anfrage, der
Webserver antwortet und der Austausch ist beendet. Wenn eine HTTP-GET-Anfrage an einen
Webserver geschickt wird und gleich darauf eine zweite Anfrage, ist das HTTP-Protokoll nicht in
der Lage, diese zwei Anfragen in Verbindung zu bringen.
Mitunter wird angenommen, dass so genannte persistente7 Verbindungen dieses Defizit
überwinden und den Status aufrechterhalten können. Das stimmt nicht. Obwohl die Verbindung
erhalten bleibt, werden die Anfragen selbst völlig unabhängig voneinander behandelt.
Das wirft mehrere Probleme in HTTP auf:
Authentifizierung - Das Protokoll erkennt Anfragen nicht als zusammen gehörig. Wenn Sie
einen Zugriff einer Person in der Anfrage A autorisieren, wie bestimmen Sie unter diesen
Voraussetzungen also, ob eine nachfolgende Anfrage B von derselben oder einer anderen Person
stammt?
Persistenz - Die meisten Leute benutzen das Internet, um Aufgaben zu erledigen. Per Definition
erfordert eine Aufgabe, dass etwas den Status ändert (ansonsten ist nichts passiert). Wie bewirken
Sie Änderungen, insbesondere Änderungen, die mehrere Schritte erfordern, wenn Sie keinen
Status haben?
Ein typisches Beispiel für eine Webapplikation, die auf dieses Problem stößt, ist ein Online-Shop.
Die Applikation muss den Benutzer authentifizieren, so dass sie weiß, wer der Benutzer ist (da sie
persönliche Angaben wie die Adresse des Benutzers und Informationen zur Kreditkarte
gespeichert hat). Außerdem muss sie bestimmte Daten - wie den Inhalt des Einkaufwagens - über
mehrere Anfragen aufrechterhalten.
Die Lösung für diese beiden Probleme liegt darin, den notwendigen Erhalt des Status selbst zu
implementieren. Diese Herausforderung ist weniger kompliziert als sie zunächst erscheinen mag.
Netzwerkprotokolle bestehen oft aus Schichten, die den Status erhalten, und die auf statuslosen
Schichten aufbauen und umgekehrt. HTTP zum Beispiel ist ein Protokoll der ApplikationsSchicht, über das zwei Applikationen (der Browser und der Webserver) Informationen
austauschen, und das auf TCP aufsetzt.
TCP ist ein Protokoll der System-Schicht (d.h. die Endpunkte sind Betriebssysteme), das
statuserhaltend ist. Wenn eine TCP-Sitzung zwischen zwei Maschinen gestartet wird, gleicht das
einem Gespräch. Die Kommunikation geht hin und her, bis eine der Parteien das Gespräch
beendet. TCP setzt auf IP auf, das ein statusloses Protokoll ist. TCP implementiert den Status
durch Reihenfolge-Nummern in den Paketen. Diese Reihenfolge-Nummern (plus die
Netzwerksadressen der Endpunkte) erlauben beiden Seiten festzustellen, ob sie irgendwelche
Teile des Gespräches verpasst haben und stellen eine Möglichkeit der Authentifizierung zur
Verfügung, so dass jede Seite weiß, dass sie noch mit derselben Person spricht. Wenn die
Reihenfolge-Nummern leicht zu erraten sind, ist es möglich, eine TCP-Sitzung zu entführen, sich
also mithilfe der richtigen Reihenfolge-Nummern in das Gespräch einzuschleichen.
7
Bezüglich der logischen Verbindungen bedeutet Persistenz, dass die reale Verbindung bei Bedarf oder nach einem Ausfall
wiederhergestellt wird, ohne dass die zwischenzeitliche Trennung durch die Kommunikationspartner bemerkt wird.
Seite 42 von 54
9.1
Einführung in die Programmierung mit PHP und MySQL.doc
Benutzerregistrierung
Bevor Sie sich um die Authentifizierung von Benutzern kümmern können, müssen Sie
wissen, wer die Benutzer sind. Sie benötigen mindestens einen Benutzernamen und ein
Kennwort, obwohl es oft nützlich ist, noch mehr Information zu sammeln. Viele
Programmierer konzentrieren sich auf die Feinheiten guter Passwort-Generierung (was
schwierig, aber notwendig ist), ohne jemals über die Möglichkeiten einer eindeutigen
Identifizierung nachzudenken.
Zu den Gefahren im Rahmen der Benutzerregistrierung siehe auch Kapitel 10.5.
9.1.1
Identifizierung
Eine sinnvolle Möglichkeit ist die Verwendung von E-Mail-Adressen als eindeutige
Identifizierung von Benutzern in Webapplikationen. Die große Mehrheit der Benutzer
(abgesehen von Computerfreaks) benutzt lediglich eine einzige Adresse. Diese Adresse wird für
gewöhnlich auch exklusiv von diesem Benutzer verwendet, so dass sie sich bestens als
vollkommen
einzigartige
Identifizierung
eines
Benutzers
eignet.
Mit
einer
Bestätigungsrückmeldung für die Anmeldung (Sie senden dem Benutzer eine E-Mail-Nachricht.
die ihn auffordert zu handeln. um die Anmeldung abzuschließen) können Sie sich davon
überzeugen, dass die E-Mail-Adresse gültig ist und dem Benutzer gehört, der sich anmelden
möchte.
Mithilfe von E-Mail-Adressen können Sie auch nachhaltiger mit Ihren Benutzern
kommunizieren. Wenn die User zustimmen, E-Mails von Ihnen zu erhalten, können Sie ihnen
periodische Informationen über die Site schicken und sind notfalls im Stande, ein neu generiertes
Passwort an einen Benutzer zu senden (wenn eine Passwort-Wiederherstellung kritisch ist). Alle
diese Aufgaben sind am saubersten durchzuführen, wenn es eine eineindeutige Zuordnung von
Benutzern und E-Mail-Adressen gibt.
Allerdings erleichtert die Verwendung der E-Mail-Adresse als Benutzername den
Identitätsdiebstahl, da diese öffentlich bekannt sind. Ein Angreifer muss also nur noch das
Passwort und nicht mehr den Nutzernamen erraten. Dieser Umstand spricht für die Generierung
eines künstlichen Nutzernamens, der allerdings auf Eindeutigkeit überprüft werden müsste.
9.1.2
Kennwörter
Benutzer wählen von Natur aus schlechte Kennwörter. So haben zahlreiche Studien
belegt, dass - wenn man es ihnen erlaubt - die meisten Benutzer ein Kennwort wählen, das
in kurzer Zeit erraten werden kann.
Wie sieht ein "gutes" Kennwort aus? Ein gutes Kennwort ist eines, das nicht leicht durch
automatisierte Techniken erraten werden kann. Ein "guter" Kennwort-Generator könnte
folgendermaßen aussehen:
function random_password($length=8){
$str ='';
for($i=O; $i<$length; $i++)
{$str .= chr(rand(48,122));
return $str;
}
Listing 9-1: Erzeugung eines Zufalls-Passwortes
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 43 von 54
Dies erzeugt Kennwörter, die aus zufälligen, druckbaren ASCII-Zeichen bestehen und
schwer zu merken sind. Damit ist das Kernproblem mit zufällig erzeugten Kennwörtern
angesprochen: Menschen hassen diese Kennwörter. Je schwieriger es ist, sich ein
Kennwort zu merken, desto größer die Wahrscheinlichkeit, dass es auf einem Notizzettel
an den Monitor geheftet, oder in eine Datei oder E-Mail-Nachricht geschrieben wird.
Alternativ wird oft der Weg gewählt, das Problem mit den Kennwörtern auf den Benutzer
abzuwälzen und ein paar einfache Regeln zu implementieren. Sie können dem Benutzer
zum Beispiel erlauben, sein eigenes Kennwort auszuwählen, aber verlangen, dass das
Kennwort bestimmte Tests besteht. Der folgende Code führt eine einfache Validierung
eines Kennworts durch:
function good_password($passwordl){
if(strlen($passwordl < 8) {
return 0;
}
if(!preg_match("/\d/", $password)){
return 0;
if(!preg_match("/[a-z]/i", $password)){
return 0;
}
return 1;
}
Listing 9-2: Prüfung eines Passwortes auf Mindestgüte
Diese Funktion verlangt, dass ein Kennwort mindestens acht Zeichen lang ist und sowohl
Buchstaben und Ziffern enthält.
Eine robustere Funktion könnte überprüfen, dass kein Wort aus einem Wörterbuch übrig
bleibt, wenn die Ziffern weg gelassen werden, oder dass weder der Name des Benutzers
noch seine Adresse im Kennwort enthalten sind. Die Frage der Kennwörter auf diese Art
zu lösen, ist eine Taktik, der man häufig begegnet: Wenn ein Problem schwer zu lösen ist,
wird es auf andere abgewälzt! Fraglos ist es gar nicht so einfach, ein sicheres Kennwort zu
erzeugen, mit dem ein Benutzer glücklich ist. Viel leichter ist es, ein schlechtes Kennwort
zu entdecken und den Benutzer davon abzuhalten, es zu wählen.
9.2
Benutzerauthentifizierung
Das hier dargestellte System ist im Wesentlichen ein auf Tickets basierendes. Denken Sie
zum Beispiel an Tickets für einen Skilift. Im Tal kaufen Sie sich ein Ticket für den Lift und
heften es an Ihre Jacke. Dadurch ist das Ticket sichtbar, wo auch immer Sie hingehen.
Wenn Sie versuchen, den Lift ohne Ticket oder mit einem nicht mehr gültigen Ticket zu
nutzen, werden Sie zum Eingang zurückgeschickt, damit Sie sich eine neue Karte kaufen.
Mit verschiedenen Maßnahmen wird sichergestellt, dass die Tickets schwer zu fälschen
sind (z. B. mit Unterschriften auf den Tickets).
Zuerst müssen Sie im Stande sein, die Berechtigung der Benutzer zu überprüfen. In den
meisten Fällen handelt es sich um einen Benutzernamen und ein Kennwort, die übergeben
werden. Sie können diese Informationen dann gegen eine Datenbank abgleichen (oder
gegen einen LDAP-Server etc.). Hier ist das Beispiel einer Funktion, die eine MySQL
Datenbank verwendet, um die Berechtigung eines Benutzers zu überprüfen:
Seite 44 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
function check_credentials($name. $password) {
$sql = “SELECT userid FROM users”;
$sql .= “WHERE username = $name AND password = $password”;
mysql_query ($abfrage);
$num = mysql_affected_rows();
if ($num > 0)
echo "Zugang gewaehrt";
else
echo "Zugang verweigert";
}
Listing 9-3: Prüfung einer Nutzerberechtigung
Die Überprüfung der Benutzerangaben ist nur eine Hälfte des Spiels. Sie brauchen auch ein
Verfahren für die Authentifizierung. Dabei können Sie zwischen drei Methoden wählen: HTTPAuthentifizierung, URL-Parameter und Cookies.
9.2.1
HTTP-Authentifizierung
Basis-Authentifizierung ist ein Authentifizierungsschema, das in HTTP integriert ist. Wenn
ein Server eine nicht berechtigte Anfrage auf eine Seite erhält, beantwortet er die Anfrage
mit diesem Header:
WWW-Authenticate: Basic realm='RealmFoo'
In diesem Header ist RealmFoo ein willkürlicher, dem Namensraum zugeteilter Name, der
geschützt wird. Der Client antwortet dann mit einem Base64-kodierten
Benutzernamen/Kennwort, um sich zu authentifizieren. Diese Art der Authentifizierung
steckt hinter den Fenstern zur Eingabe eines Benutzernamens/Kennwortes, die in vielen
Sites auftauchen. Serverseitig ist die Authentifizierung entsprechend zu konfigurieren, beim
Apache HTTP Server etwa durch Notation entsprechender durch Authentifizierungsmodule
bereitgestellter Direktiven in einer .htaccess-Datei. Der bevorzugte Weg ist jedoch die Notation
der Direktiven in der zentralen Serverkonfigurationsdatei httpd.conf.
Mittlerweile wurde die Basis-Authentifizierung jedoch weitgehend verdrängt durch die
Authentifizierung mit Hilfe von Cookies. Der große Vorteil der Basis-Authentifizierung ist,
dass sie in der HTTP-Schicht verankert ist, so dass alle Dateien auf einer Site geschützt
werden können - nicht nur PHP-Skripte. Das ist vor allem für Sites wichtig, die Video-/
Audio- und Bild-Dateien für registrierte Mitglieder anbieten, weil darüber auch der Zugriff
auf diese Mediadateien kontrolliert werden kann. In PHP stehen der Benutzername und
das Kennwort der Basis-Authentifizierung im Skript als $_SERVER['PHP_AUTH_USER'] und
$_SERVER['PHP_AUTH_PW'] zur Verfügung.
9.2.2
Session-Daten in der URL
Bei diesem Verfahren werden die Benutzerinformationen bei jeder Anfrage an die URL
angehängt. Eine Reihe von Java-Session-Wrappers funktionieren auf diese Weise und
auch im PHP-Modul für Sessions kann dieses Verfahren verwendet werden.
Diese Form der Übergabe von Session-Daten erzeugt furchtbar lange und »scheußliche«
URLs. Sessioninformationen können ziemlich umfangreich werden, und einfach 100
Bytes an die ansonsten elegante URL zu hängen, ist einfach hässlich. Aber es ist nicht nur
eine Frage der Ästhetik. Viele Suchmaschinen ignorieren dynamische URLs (d.h. URLs
mit Parametern). Hinzu kommt, dass lange URLs schwer zu kopieren sind - oft werden
sie einfach abgeschnitten, so dass sie kaum per E-Mail verschickt werden können.
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 45 von 54
Zweitens impliziert das Anhängen der Session-Daten an die URL ein Sicherheitsproblem,
weil die Parameter der Session eines Users sehr leicht zu einem anderen User gelangen
können. Durch Kopieren und Einfügen der URL mit der Session-ID kann die Session
eines Users entführt werden, manchmal auch unbeabsichtigt.
Wir werden diese Technik hier nicht weiter behandeln, da es fast immer sicherere und
elegantere Lösungen gibt.
9.2.3
Cookies
Seit Netscape 3.0 (1996) werden Cookies von Browsern unterstützt. Der folgende Abschnitt
stammt aus der Spezifikation für Cookies von Netscape:
Ein Server kann, wenn er ein HTTP-Objekt zum Client schickt, auch eine Status-Information
mitsenden, die der Client speichern wird. Integriert in dieses Statusobjekt ist eine Beschreibung
eines URL-Bereichs, für die der Status gültig ist. Jede zukünftige HTTP-Anfrage dieses Clients,
die in diesen Bereich passt, enthält den aktuellen Wert des Statusobjekts, das somit vom Client
zurück zum Server geschickt wird. Dieses Statusobjekt wird - aus welchen Gründen auch immer als Cookie bezeichnet.
Cookies stellen ein unschätzbares Werkzeug zur Verfügung, um den Status zwischen Anfragen
aufrechtzuerhalten. Über die Übertragung von Benutzerinformationen und Authentifizierungen
hinaus können Cookies effektiv zur Übergabe großer und beliebiger Statusinformationen
zwischen Anfragen verwendet werden, selbst nachdem der Browser geschlossen und erneut
geöffnet worden ist.
Cookies sind der de facto Standard, um transparent Informationen per HTTP-Anfragen zu
übergeben. Hier sind die wichtigsten Vorteile von Cookies gegenüber der BasisAuthentifizierung:
Vielseitigkeit - Cookies bieten eine ausgezeichnete Möglichkeit, vielseitige Informationen
zwischen Anfragen zu übergeben. Basis-Authentifizierung ist, wie der Name schon sagt,
rudimentär.
Persistenz - Cookies können im Browser des Users über Sitzungen hinweg gesetzt werden (die
Cookies bleiben auch erhalten, wenn der Browser geschlossen und wieder gestartet wird). Viele
Seiten nutzen diesen Vorteil, um transparentes oder automatisches Einloggen - basierend auf den
Informationen der Cookies - zu ermöglichen. Selbstverständlich hat dieses Verfahren
Auswirkungen auf die Sicherheit, aber auf vielen Sites wird ein Teil der Sicherheit zugunsten der
Benutzerfreundlichkeit geopfert. Natürlich können Benutzer den Browser so einrichten, dass
Cookies von einer Site abgelehnt werden. Es liegt an Ihnen, wie viel Aufwand Sie mit Menschen
betreiben, die »paranoide« Cookie-Einstellungen verwenden.
Ästhetik - Basis-Authentifizierung ist das Verfahren, bei dem der Browser ein kleines Fenster für
den Benutzernamen/ das Kennwort öffnet. Dieses Fenster ist nicht an das Design der Site
angepasst, und das ist für viele Sites inakzeptabel. Mit einem selbst gemachten Verfahren sind Sie
flexibler.
Sofern Anmeldedaten oder interne Werte in Cookies gespeichert werden, sollten diese unbedingt
verschlüsselt sein. Cookies zu untersuchen und zu verändern ist für einen Benutzer trivial; um so
wichtiger ist es, dass die Daten im Cookie in einem Format gespeichert werden, in dem der
Benutzer ihre Bedeutung nicht sinnvoll ändern kann. Versuchen Sie nicht, eigene
Seite 46 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Verschlüsselungsalgorithmen zu entwickeln, die Erweiterung mycrypt stellt eine große Anzahl
überprüfter Algorithmen zur Verfügung.
Die bessere Variante ist es aber, im Cookie nur Verbindungsinformationen zu speichern,
während alle anderen Daten auf dem Server verbleiben. So hat der Nutzer keinen direkten
Zugriff und kann Informationen nur schwer böswillig ändern. Diese Form wird in Kapitel 9.3.2
genauer beschrieben.
Die Lebensdauer eines Cookies bestimmt die Dauer der Gültigkeit einer Authentifizierung. Einen
Auslogvorgang können Sie realisieren, indem Sie das Session-Cookie leeren. Die Möglichkeit zum
Ausloggen ist ein wichtiger Bestandteil der Privatsphäre des Nutzers. Daneben gibt es weitere
Möglichkeiten, die Lebensdauer eines Cookies zu begrenzen:
 Verfall bei jeder Anfrage
Dieses Verfahren erschwert die Entführung einer Session, erfordert aber beträchtliche
Ressourcen auf dem Server. In den meisten Fällen rechtfertigt der Sicherheitsgewinn nicht
den zusätzlichen Aufwand.
 Verfall nach festgelegter Zeitspanne
Dieses Verfahren wird häufig angewendet. Es entspricht unserem Eingangsbeispiel des
Skilift-Tickets. Bei der Erstellung des Cookies wird die Gültigkeitsspanne festgelegt und die
Ausgabezeit im Cookie vermerkt. Bei einem erneuten Seitenaufruf innerhalb einer Session
wird dann die Gültigkeit der Session gegen diese Zeit geprüft und die Ausgabezeit neu
gesetzt.
 Verfall beim Schließen des Browsers
Hier löscht der Browser das Cookie beim Schließen des Browserfensters. Die Daten auf dem
Server bleiben dabei zunächst bestehen. Für Ihre Vernichtung sorgt der "Müllmann", die
Garbage Collection. Standardmäßig wird der Garbage Collector eine inaktive Session nach
frühestens 24 Minuten beseitigen. Nach diesem Zeitfenster könnte also auch ein noch
geöffneter Browser nicht mehr zugriffsautorisiert sein.
9.3
Statuserhalt durch Sessions
Wie wir zu Beginn des Kapitels festgestellt haben, ist http ein verbindungsloses Protokoll. Das
heißt, ein Webserver erstellt mit Hilfe von PHP Dokumente, die ein Client angefordert hat und
liefert diese zurück an den Browser. Danach vergisst der Webserver diese Seite und auch den
Client. Sessions stellen nun die Verbindung zwischen Server und Client her. Sie speichern
Sitzungsdaten und Daten, die einen Benutzer eindeutig identifizieren. An dieser Stelle soll nur die
Funktionsweise von Sessions behandelt werden, ein Beispiel, wie Sessions zur
Benutzerauthentifizierung eingesetzt werden können, wird in Kapitel 9.3.4 behandelt.
Für die Mechanismen von Sessions ist ein Session-Management verantwortlich. Dieses speichert
lokale Daten und eine eindeutige ID. Ein solcher Mechanismus ist für dynamische Seiten
notwendig, die während eines mehrstufigen Programmablaufs (z.B. einem Online-Einkauf) auf
die Identifikation eines Benutzers angewiesen sind.
Die eindeutige Identifikation, die der Webserver jedem Besucher zu Beginn der Sitzung zuteilt,
heißt Sitzungs- oder Session-ID. Diese wird in der Regel automatisch zugewiesen. Wie viele
andere Skriptsprachen hat PHP dafür einen eingebauten Session-Manager. Bei anderen Sprachen
muss ein solcher Mechanismus selbst nachgerüstet werden. Die Sicherheit einer Session hängt
stark von der Qualität des Session-Managements ab, das PHP-eigene gilt hier als vorbildlich.
Einführung in die Programmierung mit PHP und MySQL.doc
9.3.1
Seite 47 von 54
Das Session-Management von PHP
Eine Session wird in PHP durch den Aufruf der Funktion session_start() erzeugt. Der Befehl
erzeugt eine neue Session oder nimmt eine bestehende wieder auf. Die Identifikation der Session
erfolgt dabei über die zwischen Browser und Server übermittelte Session-ID.
Das Session-Management von PHP legt auf dem Webserver eine Datei im dafür vorgesehenen
Verzeichnis an und speichert dort alle Session-Daten. Erreichbar sind die Daten über die
Systemvariable $_SESSION, die ein Array darstellt. Der Client erhält vom Server nur die SessionID, die die Sitzung auf dem Server identifiziert – und meist gleichzeitig der Name der SessionDatei ist. Es handelt sich hier also um eine Server-Session, die schon dadurch, dass Nutzdaten
den Server nicht verlassen, sicherer ist als eine Client-Session.
Die Session-ID kann auf drei Arten zwischen Browser und Server übermittelt werden:
 in einem Cookie.
Das Cookie wird bei jedem Request als HTTP-Header an den Webserver mitgeschickt. Das
Cookie wird vom PHP-Interpreter bzw. von der Applikation ausgestellt. Es kann persistent
(dauerhaft) oder nicht-persistent sein. Letztere Cookies verfallen mit dem Schließen des
Browsers, erstere werden für längere Zeit (oft dauerhaft und ohne Wissen des Nutzers) auf
der Festplatte des Clients gespeichert. Das Versenden der Session-ID in einem Cookie ist der
Standard in PHP und auch der sicherste Weg, dieser Mechanismus sollte nicht ohne Grund
geändert werden.
 in der URL-Anfrage.
Hier sind zwei Arten der Übertragung möglich:
 URL-Rewriting – Die Session-ID ist Teil der URL, z.B. http://SESSION1234.mysite.de
(Achtung, Patentschutz!) oder http://www.mysite.de/SESSION1234/index.php.
 $_GET-Parameter – Hier wird die Session-ID an den bereits vorhandenen Query-String
als weiterer Parameter angehängt, z.B.
http://www.mysite.de/index.php?PHPSESSION=SESSION1234.
In der Regel wird der URL-Transport nur eingesetzt, wenn der Client keine Cookies erlaubt.
Über die trans_sid-Funktionalität entscheidet PHP automatisch, welche Transportmethode
benutzt werden soll. Aufgrund der Sichtbarkeit der Session-ID ist es leichter, eine URLtransportierte Session zu entführen.
 als Formularfeld.
Das Versenden in einem versteckten Formularfeld wird von PHP nicht standardmäßig
eingesetzt. Das folgende Beispiel stände im $_POST-Array zur Verfügung:
<input type="hidden" name="PHPSESSID" value="1234" />
9.3.2
Freizügigkeit einer PHP-Session
Bei der Sessionverwaltung unterscheidet man zwischen permissiven (freizügigen) und strikten
Systemen. In permissiven Systemen erhält jeder eine Session-ID. Falls eine vom Client
übermittelte Session-ID noch nicht existiert, wird diese auf dem Server angelegt. Das bedeutet,
ein Benutzer kann sich eine Session-ID ausdenken und diese an den Server übermitteln. Würde
es sich um ein striktes System handeln, würde diese Session-ID verworfen und durch eine von
der Sprache erzeugte ID ersetzt werden. Strikte Systeme sind also für Angriffe wie Session-Riding
(das Ausführen von Aktionen unter fremden Sessions) oder Phishing weniger anfällig.
PHP implementiert das permissive Session-Modell. Der Einbau von Restriktionen muss vom
Programmierer durchgesetzt werden. Grundsätzlich sollte bei der Vergabe einer Session-ID
geprüft werden, ob der Nutzer schon authentifiziert ist und ob ihm eine Rolle zugeordnet wurde.
Seite 48 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Jede Seite der Applikation muss diese Authetifizierungsdaten erneut prüfen, um den Quereinstieg
in tiefer liegende Ebenen zu verhindern.
9.3.3
Daten einer Session verwalten
Das Session-System von PHP speichert die Session-Daten in der Standardinstallation in dem
Verzeichnis, das in der Konfigurationsdatei php.ini im Wert session.save_path festgelegt wurde. Dies
geschieht in einem für Menschen lesbaren Format als serialisiertes Array. Auf einem
Hostingserver (Mehrbenutzer-System) hat unter Umständen jeder Benutzer Zugriff auf die
Session-Daten anderer Nutzer. Jeder Nutzer muss also Sorge tragen (durch eine eigene php.ini),
die Daten in einem eigenen Verzeichnis abzulegen, zu dem nur er Zugriffsrechte hat.
Das Array, welches die Session-Daten enthält, kann neben der Session-ID beliebige andere Daten
beinhalten. Zugriff erhält man über die Systemvariable $_SESSION. Um z.B. den Status eines
Nutzers über die verschiedenen Seiten einer Session verfügbar zu haben, kann man ihn unter
$_SESSION['status'] = XX abspeichern. So lassen sich beliebig viele Daten innerhalb einer
Session weitergeben.
9.3.4
Beispiel: Session zur Benutzerauthentifizierung
Für die Erzeugung einer Session (und die Versendung des zugehörigen Cookies) ist es wichtig,
dass noch kein http-Header versendet wurde. Die folgenden Zeilen erzeugen eine
Fehlermeldung:
<html>
<?php
session_start();
…
Der Zeilenumbruch hinter dem <html>-Tag ist ein darstellbares Zeichen und führt zur
Versendung des http-Headers, ein Versenden des Cookies ist nicht mehr möglich.
Mit jeder neuen Anfrage versendet der Browser auch das Cookie an den Server. Dieser ist somit
in der Lage, die Anfrage einer bestimmten Session zuzuordnen. Wichtig ist dazu, dass jede Seite
die Session neu startet. Eine einfache Anmeldung mit Rechtesystem könnte also wie folgt
ablaufen:
<html>
<head>
<title>Benutzerzugangskontrolle - Login</title>
</head>
<body>
<h1>Anmeldung an der Website</h1>
<form method="post" action="auth2.php">
<input type="text" name="benutzer"> Benutzername<br>
<input type="password" name="password"> Password<br>
<input type="submit">
</form>
</body>
</html>
Listing 9-4: auth1.php - Eingabeformular Benutzeranmeldung
Die Datei auth1.php stellt lediglich ein Eingabeformular zur Abfrage von Nutzername und
Passwort zur Verfügung. Da hier noch keine Auswertung erfolgt, ist auch noch kein Start einer
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 49 von 54
Session nötig. Die Auswertung der Eingaben erfolgt in der aufgerufenen Datei auth2.php. Hier
wird die Richtigkeit der eingegebenen Daten überprüft (bzw. deren Übereinstimmung mit einem
Datenbankeintrag, hier in der Tabelle "users"). Für die weitere Arbeit auf den Folgeseiten werden
dann nötige Daten in der Sessionvariablen gespeichert.
<?php
// Start der PHP-Session
session_start ();
$eingabename = $_POST["benutzer"];
// Password MD5-verschlüsseln!
$eingabepasswort = md5($_POST["password"]);
// Abfrage der Datenbank
mysql_connect ("", "root", "");
mysql_select_db("phpskript");
$abfrage = "SELECT Name, Vorname, Rechte FROM nutzer";
$abfrage .= " WHERE Username = '$eingabename'";
$abfrage .= " AND Password = '$eingabepasswort'";
$res = mysql_query ($abfrage);
$num = mysql_num_rows ($res);
?>
<!-- Kopfdaten in HTML -->
<html>
<head><title>Benutzerzugangskontrolle - Auswertung</title></head>
<body>
<?php
// Ein Datensatz identifiziert?
if ($num == 1){
// Sichern der Nutzermerkmale zur späteren Verwendung
$dsatz = mysql_fetch_array ($res);
$_SESSION["name"] = $dsatz["Name"];
$_SESSION["vorname"] = $dsatz["Vorname"];
$_SESSION["rechte"] = $dsatz["Rechte"];
// Begrüßung
echo "<p>Hallo ".$_SESSION["vorname"]." ".$_SESSION["name"]."</p>";
// Auswahlmenü zur weiteren Arbeit
?>
<h1>Hier geht es zu den gesch&uuml;tztenSeiten</h1>
<p><a href="auth3.php">Zur Seite 'Zugang mit Recht 0'</a></p>
<p><a href="auth4.php">Zur Seite 'Zugang mit Recht 1'</a></p>
<p><a href="auth5.php">Zur Seite 'Zugang mit Recht 2'</a></>
<?php
}else{
?>
<h1>Fehler in den Eingabedaten</h1>
<a href="auth1.php">Zur&uuml;ck zur Anmeldung</a>
<?php
}
?>
</body></html>
Listing 9-5: auth2.php - Auswertung der Nutzeranmeldung
Die folgende Datei (auth5.php - Beispiel einer Rechteprüfung) zeigt beispielhaft die Auswertung
der in der Session gespeicherten Angaben. Die Prüfung auf Zugangsberechtigung muss auf jeder
aufgerufenen Seite erfolgen. In dem Beispiel wird ein hierarchisches Rechtesystem vorausgesetzt,
bei dem eine größere Kennzahl der Berechtigung auch erweiterte Rechte bedeuten. Auf der
Beispielseite soll eine Berechtigung von 2 oder größer gefordert sein.
Seite 50 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
<?php
// Wiederherstellen der Session
session_start ();
$zugang = true; // Zugangsberechtigung vorerst vorausgesetzt
?>
<!-- Kopfdaten in HTML -->
<html>
<head><title>Benutzerzugangskontrolle - Nutzerseite 0</title></head>
<body>
<?php
// Prüfung, ob die nötigen Sessiondaten existieren
if (isset ($_SESSION["name"]) AND isset ($_SESSION["vorname"])){
echo "<p>Hallo ".$_SESSION["vorname"]." ".$_SESSION["name"]."!</p>";
}else{
$zugang = false;
}
// Prüfung auf die geforderte Zugangsberechtigung (hier:2)
if ($_SESSION["rechte"] < 2) $zugang = false; // fehlende Berechtigung!
// hier erfolgt der eigentliche Zugang zur Seite
if ($zugang){
echo "<p>Zugang gew&auml;rt</p>";
}else{
echo "<p>";
echo "F&uuml;r diese Seite haben Sie nicht die n&ouml;tigen Rechte";
echo "</p>";
}
?>
</body></html>
Listing 9-6: auth5.php - Beispiel einer Rechteprüfung
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 51 von 54
10 Angriffsszenarien
10.1 Informationsgewinnung
Zur Zeit noch nicht bearbeitet
10.2 Parametermanipulation
Zur Zeit noch nicht bearbeitet
10.3 Cross-Site-Scripting
Zur Zeit noch nicht bearbeitet
10.4 SQL-Injection
Die „SQL-Einschleusung“ ist das Ausnutzen einer Sicherheitslücke im Zusammenhang mit SQLDatenbanken. Die meisten Anwendungen speichern in Formularen eingegebene Daten zur
späteren Weiterverwendung in Datenbanken. Bei diesem Angriff wird nun versucht, über die
Eingabe von Metazeichen in das Eingabeformular eigene SQL-Befehle einzuschleusen. Solche
Metazeichen sind z.B. der Backslash (\), das Anführungszeichen (”), der Apostroph (’) und das
Semikolon (;).
Werden Formularinhalte ungeprüft in Datenbanken gespeichert, kann dadurch Schadcode
eingeschleust werden. Das Ausspähen von Zugangsdaten könnte z.B. wie folgt geschehen:
o
o
o
o
o
o
o
In einem Formular „Artnum“ wird die Eingabe einer Artikelnummer zur Ausgabe der
Artikeldaten erwartet. Die zugehörige SQL-Anweisung lautet dabei
SELECT name, beschreibung, preis FROM artikel WHERE artNr = $_POST[‚Artnum’];
Erwartet wird also eine Nummer, die den Artikeldatensatz kennzeichnet.
Ein Angreifer gibt in das Formular folgendes ein:
2 UNION SELECT name, passwort, ‚x’ FROM nutzer
Die vollständige SQL-Anweisung lautet dann:
SELECT name, beschreibung, preis FROM artikel WHERE artNr = 2 UNION SELECT
name, passwort, ‚x’ FROM nutzer;
Das ‚x’ ist notwendig, da UNION in beiden Abfrageteilen die gleiche Anzahl an von Spalten
erwartet. Diese Anzahl kann durch Ausprobieren herausgefunden werden.
Die Webseite gibt nun die Artikeldaten des Artikels 2 (wenn vorhanden) aus und alle
Nutzernamen mit den dazugehörigen Passwörtern.
Seite 52 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Zum Angriff können grundsätzlich alle Daten verwendet werden, die der Client an den Server
übermittelt und die nicht korrekt validiert werden. Dies kann GET, POST, aber auch Cookies
betreffen.
10.4.1 Get-Parameter
Daten, die an die URL angehängt werden, sind sichtbar und naturgemäß leicht zu ändern. Durch
die Schreibweise /index.php?NameDesFormularfeldes=Inhalt lassen sich
Schwachstellen besonders leicht identifizieren. Ändert man einen (oder mehrere) der Parameter,
so können Effekte auftreten, die der Entwickler nicht bedacht hat. Durch Anhängen von ' oder "
an den Parameter können z.B. Fehlermeldungen hervorgerufen werden:
Die Veränderung des Aufrufs index.php?Artikelnummer=1000 durch Anhängen von
'" erzeugt einen Syntaxfehler der Datenbank. Die dem Aufruf
mysql_query ('SELECT * FROM artikel WHERE artikelnummer='.$_GET['Artikelnummer']);
zugehörige Abfrage lautet dann:
SELECT * FROM artikel WHERE artikelnummer='1000'"
Dies erzeugt die Fehlermeldung:
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in …
Anhand dieser Fehlermeldung ist nun die Datenbank bekannt. Weitere Ausspähungen können
nun gezielt erfolgen.
10.4.2 POST-Parameter
Die Manipulation von POST-Parametern ist nicht so einfach wie bei Get-Parametern, aber nicht
unmöglich. Dazu muss das Formular lokal gespeichert werden. Dann ergänzt man das actionAttribut des Formulars um die zugehörige URL. Dies ist notwendig, da der Aufruf der Zielseite
nicht mehr im ursprünglichen Umfeld erfolgt. Nun können lokal im Browser alle Formularfelder
auf Schwachstellen untersucht werden.
Textfelder werden meist validiert, da hier eine einfache Eingabe von Sonderzeichen in das
Orginalformularfeld zum Angriff genügt. Deshalb sind besonders Radiobutton, Checkboxen
oder Listboxen für Angriffe interessant, da Entwickler hier häufig der Ansicht sind, dass nur die
vorbelegten Werte an den Server übermittelt werden können. Dies ist aber definitiv falsch. Durch
das lokale Speichern können beliebige weitere Auswahloptionen erstellt werden.
10.4.3 Cookie-Parameter
In letzter Zeit wurden auch Cookie-Parameter zu Angriffen ausgenutzt. Dies ist aber nur
möglich, wenn das Cookie über die Session-ID hinaus Werte enthält, die im Programm genutzt
werden. Ein Angriff ist dann möglich, wenn Werte aus den superglobalen Array $_COOKIE in
einer SQL-Abfrage übernommen werden.
10.4.4 Schutz vor SQL-Injektion
Sonderzeichen können mit dem PHP-Befehl mysql_real_escape_string() maskiert werden. Somit
haben diese keinen Einfluss mehr auf die SQL-Abfrage und werden nicht in der Datenbank
gespeichert.
Die Einstellung magic_quotes_gpc = on in der Konfigurationsdatei php.ini maskiert ebenfalls alle
aus GET, POST oder Cookie-Variablen stammenden Sonderzeichen mit dem Backslash. Dieser
wird aber in den String eingefügt und somit in der Datenbank gespeichert. Zudem ist dieser
Einführung in die Programmierung mit PHP und MySQL.doc
Seite 53 von 54
Mechanismus, der nur einfache und doppelte Anführungszeichen sowie den Backslash und den
NULL-Wert maskiert, als Schutz vor einer SQL-Injektion unzureichend.
Hat man keinen Zugriff auf die Datei php.ini ist häufig nicht klar, ob magic_quotes gesetzt sind
oder nicht. Ein zusätzliches (notwendiges) maskieren mit dem o.g. PHP-Befehl würde eventuell
eine doppelte Maskierung erzeugen, was unerwünscht ist. Man behilft sich dann häufig mit der
Prüfung auf die gesetzten magic_quotes { if (magic_quotes_gpc ()) } und führt dann die Funktion
stripslashes() auf den String aus. Dieser entfernt eventuell vorhandene Maskierungen. Danach
kann mit obigem PHP-Befehl neu maskiert werden. In jedem Fall ist die Maskierungen von
Sonderzeichen der Mindeststandard zum Schutz vor SQL-Injektions.
Wie in der Kapiteleinleitung zu erkennen ist, existieren auch Angriffsszenarien ohne die
Verwendung von Sonderzeichen. Es sollte deshalb zusätzlich auf bestimmte Schlüsselwörter
gefiltert werden. Hier sind besonders die Schlüsselwörter AND, OR, SELECT, UNION und
ORDER berücksichtigt werden. Zudem sollten Feldinhalte auf zulässige Werte geprüft werden;
Zahlenfelder sollten z.B. nur Ziffern enthalten und keine Buchstaben. Das Prüfen auf
Schlüsselwörter kann u. U. problematisch sein, wenn diese als zulässige Inhalte vorkommen
können ( beispielsweise als Name der Firma "Papier Union").
Einen guten Schutz bieten auch die mit der "neuen" MySQL-Extension "mysqli" eingeführten
"Prepared Statements" sowie das in MySQL 5.0 neu eingeführte Feature "Stored Procedures".
Beide Varianten machen enge Vorgaben für die abzuarbeitenden SQL-Statements, was Angriffe
erschwert oder sogar verhindert. Ihre Behandlung sprengt aber den Rahmen dieser Einführung.
10.5 Autorisierung und Authentifizierung
Für Login- und Anmeldeseiten jeder Art sollte SSL als absolutes Muss angesehen werden. Der
Einsatz von SSL erfüllt zweierlei Aufgaben. Zum einen werden alle Daten zwischen Server und
Client verschlüsselt übertragen, zum anderen kann der Client anhand eines sogenannten
Zertifikates Ihre Identität nachprüfen. Solche Zertifikate werden von anerkannten Certificate
Authorities (CA) wie z.B. VeriSign ausgestellt.
10.5.1 Man-in-the-Middle-Attacke
Bei diesem Angriff leitet der Cracker den Datenverkehr (und die Verifikation eines SSLZertifikates) so um, dass ein von ihm gefälschtes Exemplar präsentiert wird, das jedoch meist
nicht von einer anerkannten CA unterschrieben ist. Leitet er zusätzlich den DNS-Eintrag Ihrer
Websites auf eine andere IP um, indem er (über Viren oder Würmer) die DNS-Funktion der
Kunden manipuliert (Pharming), kann er Angriffe wie etwa das Abfischen von Passwörtern und
Nutzerdaten (Phishing) perfektionieren. Ein von einer im Browser anerkannten CA ausgestelltes
Zertifikat verhindert solche Man-in-the-Middle-Attacken.
10.5.2 Wörterbuchangriff
Ein Wörterbuchangriff ist ein automatisierter Angriff gegen ein Authentifizierungssystem. Ein
Hacker verwendet im Allgemeinen eine große Datei mit potenziellen Kennwörtern (zum Beispiel
alle aus zwei Wörtern zusammengesetzten Begriffe der englischen Sprache), und versucht hinter
einander, sich mit diesen Begriffen in ein Konto einzuloggen. Diese Art Angriff funktioniert zwar
nicht bei zufällig generierten Kennwörtern, aber sie ist unglaublich erfolgreich, wenn Benutzer
ihre eigenen Kennwörter wählen können.
Seite 54 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Die Herausforderung liegt darin, Wörterbuchangriffe gegen das Authentifizierungssystem zu
verhindern. Letztendlich werden Wörterbuchangriffe die Sicherheit des Benutzers immer
gefährden. Der Umfang verständlicher Kennwörter ist begrenzt und dagegen können noch so
gute Regeln zur Vermeidung schlechter Kennwörter nichts ausrichten.
Eine Lösung besteht darin, einen Account zu sperren, wenn es bei der Anmeldung
mehrere Fehlschläge hintereinander gegeben hat. Die Implementierung ist ganz leicht. Sie
können die ursprüngliche Funktion check_credentials so modifizieren, dass nur
eine begrenzte Anzahl von Fehlschlägen zugelassen wird, bevor der Account gesperrt wird:
Dazu schreiben Sie das Datum des letzten Fehlversuchs sowie die Anzahl der fehlerhaften
Anmeldeversuche in den Nutzerdatensatz. Überschreitet die Anzahl einen vorgegebenen
Wert, ist eine Anmeldung nicht mehr möglich.
Die Aufhebung kann manuell oder durch einen Cronjob erfolgen, der die Anzahl der
Fehlschläge für die Datensätze wieder auf Null setzt, bei denen der letzte Fehlschlag mehr
als eine Stunde zurück liegt.
Der Nachteil dieser Methode liegt darin, dass ein Hacker den Zugriff auf einen Account
einer Person sperren kann, indem er absichtlich mehrfach ein falsches Kennwort eingibt.
Als wenigstens partielle Lösung dieses Problem können Sie versuchen, fehlgeschlagene
Anmeldungen an die IP zu binden. Sicherheit bei der Anmeldung zu garantieren ist ein
endloser Kampf. Es gibt kein System, dass nicht missbraucht werden kann. Wichtig ist es,
die potenziellen Risiken gegen den zeitlichen Aufwand und die Ressourcen abzuwägen,
durch die Gefahren des Missbrauchs begrenzt werden können.
10.5.3 Social Engineering
Obwohl es kein technisches Problem ist, sollte man nicht über Anmeldesicherheit sprechen,
ohne das so genannte »Social Engineering« zu erwähnen. Der Trick dieser Angriffe besteht darin,
den Benutzer dazu zu bringen, vermeintlich vertrauenswürdigen Personen Informationen zu
verraten. Dabei wird u.a. zu folgenden Tricks gegriffen:
 Man gibt sich als System-Administrator der Site aus und schickt E-Mail-Nachrichten, in
denen die Benutzer aus »Sicherheitsgründen« um ihre Kennwörter gebeten werden.
 Man kreiert eine Imitation der Anmeldungsseite und der Benutzer wird verleitet, sich auf
dieser falschen Seite einzuloggen.
 Es wird versucht, eine Kombination dieser beiden Tricks anzuwenden.
Es ist schwer zu glauben, dass Benutzer auf diese Tricks reinfallen, aber sie tun es sehr häufig.
Eine Suche bei Google nach Betrügereien im Zusammenhang mit eBay bringt eine Vielzahl
solcher Versuche zu Tage.
Es ist gar nicht einfach, sich gegen dieses Vorgehen zu schützen. Der Kern des Problems liegt
darin, dass die Angriffe nicht technischer Natur sind, sondern dass sie die Benutzer einfach nur
zu Leichtsinn verleiten. Als Gegenmaßnahme kann man lediglich versuchen, Benutzer zu
erziehen. Man muss ihnen klar machen, wie und warum man sich mit ihnen in Verbindung setzen
könnte und Ihnen ein gesundes Misstrauen gegen die Weitergabe persönlicher Information
einimpfen.
Einführung in die Programmierung mit PHP und MySQL.doc
11 Objektorientierte Programmierung in PHP 5
Dieses Kapitel folgt in einer späteren Version
Seite 55 von 54
Seite 56 von 54
Einführung in die Programmierung mit PHP und MySQL.doc
Anhang: Verzeichnisse
Abbildungsverzeichnis
Abbildung 1-1:
Abbildung 1-2:
Abbildung 1-3:
Abbildung 3-1:
Abbildung 4-2:
Abbildung 5-1:
Abbildung 5-3:
PHP1-1.htm ................................................................................................................... 3
PHP1-2.htm ................................................................................................................... 4
PHP1-3.htm ................................................................................................................... 5
PHP3-1.php ................................................................................................................... 7
PHP4-2.php ................................................................................................................. 10
PHP5-1.htm ................................................................................................................. 12
Uebung5-2.php ............................................................................................................ 13
Tabellenverzeichnis
Tabelle 1:
Tabelle 2:
Tabelle 3:
Tabelle 4:
Rechenoperatoren ......................................................................................................... 9
Umwandlung von Zeichenketten in Zahlen ................................................................. 14
Vergleichsoperatoren ................................................................................................... 15
Rangordnung der Operatoren ...................................................................................... 16
Verzeichnis der Beispiel-Listings
Listing 1-1:
Listing 1-2:
Listing 1-3:
Listing 2-1:
Listing 3-1:
Listing 4-1:
Listing 4-2:
Listing 5-1:
Listing 5-2:
Listing 6-1:
Listing 6-2:
Listing 6-3:
Listing 6-4:
Listing 6-5:
Listing 6-6:
Listing 6-7:
Listing 6-8:
Listing 6-9:
Listing 6-10:
Listing 6-11:
Listing 6-12:
Listing 7-1:
Listing 7-2:
Listing 8-1:
Listing 8-2:
Listing 8-3:
Listing 8-4:
Listing 8-5:
Listing 8-6:
Listing 8-7:
Listing 8-8:
Listing 8-9:
Listing 8-10:
Listing 8-11:
Listing 8-12:
Listing 9-1:
Listing 9-2:
PHP1-1.htm ................................................................................................................... 3
PHP1-2.htm ................................................................................................................... 4
PHP1-3.htm ................................................................................................................... 5
PHP2-1.php ................................................................................................................... 6
PHP3-1.php ................................................................................................................... 7
PHP4-1.php ................................................................................................................... 9
PHP4-2.php ................................................................................................................. 10
PHP5-1.htm ................................................................................................................. 11
PHP5-1.php ................................................................................................................. 12
PHP6-1.php ................................................................................................................. 17
PHP6.2.php .................................................................................................................. 17
PHP6-3.php ................................................................................................................. 18
PHP6-4.php ................................................................................................................. 18
PHP6-5.php ................................................................................................................. 19
PHP6-6.php ................................................................................................................. 20
PHP6-7.php ................................................................................................................. 21
PHP6-8.php ................................................................................................................. 22
PHP6-9.php ................................................................................................................. 22
PHP6-10.php ............................................................................................................... 23
PHP6-11.php ............................................................................................................... 23
PHP6-12.php ............................................................................................................... 24
PHP7-1.php ................................................................................................................. 26
PHP7-2.php ................................................................................................................. 28
PHP8-1.php ................................................................................................................. 29
PHP8-2.php ................................................................................................................. 31
PHP8-3.php ................................................................................................................. 32
PHP8-4.htm ................................................................................................................. 33
PHP8-4.php ................................................................................................................. 34
PHP8-5.htm ................................................................................................................. 34
PHP8-5.php ................................................................................................................. 35
PHP8-6.php ................................................................................................................. 36
PHP8-7.php ................................................................................................................. 37
PHP8-8.php ................................................................................................................. 39
PHP8-9.php ................................................................................................................. 39
PHP8-10.php ............................................................................................................... 40
Erzeugung eines Zufalls-Passwortes .......................................................................... 42
Prüfung eines Passwortes auf Mindestgüte ................................................................ 43
Einführung in die Programmierung mit PHP und MySQL.doc
Listing 9-3:
Listing 9-4:
Listing 9-5:
Listing 9-6:
Seite 57 von 54
Prüfung einer Nutzerberechtigung ............................................................................... 44
auth1.php - Eingabeformular Benutzeranmeldung ...................................................... 48
auth2.php - Auswertung der Nutzeranmeldung ........................................................... 49
auth3.php - Beispiel einer Rechteprüfung ................................................................... 50
Quellenverzeichnis
Kunz, Esser, Prochaska: PHP-Sicherheit. PHP/MySQL-Webanwendungen sicher programmieren.
2., aktualisierte und überarbeitete Auflage, dpunkt.verlag: Heidelberg 2007