next up previous contents index
Next: Reguläre Ausdrücke Up: Einführung PHP Previous: PHP & mySQL

Unterabschnitte


PHP & HTTP


Header

Neben der eigentlichen Seite schickt der Server an den Client (Browser) noch einige Zusatzinformationen. Diese werden vor der eigentlichen Seite im sog. Header gesendet. Mit diesen Informationen sagt der Server z.B., ob die angezeigte Seite wirklich die gewünschte Seite ist (Status `200 Found`), oder ob die Seite nicht gefunden werden konnte und deshalb eine Fehlerseite angezeigt wird (Status `404 Not Found`). Auch kann der Server dem Client mitteilen, daß die Seite sich unter einer anderen Adresse befindet (Status `301 Moved Permanently` oder `302 Found`). Es kann auch die Aufforderung geschickt werden, sich zu authentifizieren (Status `401 Unauthorized` ).

Zusätzlich zum Status einer Seite kann auch übermittelt werden, wann die Seite zum letzten Mal verändert wurde (Last-Modified), ob sie gecacht werden darf (Cache-Control) und wenn ja wie lange (Expires), oder welchen Typ ihr Inhalt hat (Content-Type).

Normalerweise sendet der Webserver (in der Regel Apache) automatisch den richtigen Header. Mit PHP kann man den gesendeten Header allerdings beeinflussen. Zu beachten ist, daß kein einziges Zeichen vor der header-Anweisung ausgegeben werden darf! Wenn PHP als CGI installiert ist, gibt es außerdem einige Einschränkungen, z.B. kann keine Authentifizierung gemacht werden.

Wie der Header aussehen muß, ist in dem RFC[*] 2616 festgelegt. Er spezifiziert das HTTP/1.1 Protokoll. Im Folgenden zeige ich ein paar Möglichkeiten der Anwendung der header-Anweisung.


Weiterleiten

Wie bereits oben erwähnt, kann man, neben JavaScript, auch mit PHP den Client auf eine andere Seite weiterleiten. Dies geschieht mit folgender Anweisung:
header('Location: absolute_URL');
exit;
absolute_URL muß natürlich durch die gewünschte URL ersetzt werden. Es muß nach RFC die absolute URL angegeben werden, auch wenn fast alle Browser eine relative verstehen!

Das exit ist nicht unbedingt notwendig, allerdings würde es nichts bringen, nach dem header noch etwas auszugeben, da es sowieso nicht angezeigt wird.

Bei dieser Anweisung sendet Apache automatisch den Statuscode 302.


Nicht gefunden

Wenn Du Apache so konfiguriert hast, daß er als Fehlerseite eine PHP-Seite anzeigt, wird als Statuscode 200 (OK) gesendet. Da dies aber unpraktisch ist, weil so z.B. Suchmaschinen Deine Fehlerseite in ihren Index aufnehmen, solltest Du den Statuscode 404 (Not Found) senden, wodurch diese Seite als Fehlerseite erkannt wird. Die Anweisung dazu lautet wie folgt:
header('HTTP/1.0 404 Not Found');


Authentifizierung

Mit PHP besteht die Möglichkeit, den Browser ein Fenster öffnen zu lassen, in dem Name und Paßwort eingetragen werden müssen. Wenn PHP nicht als Modul, sondern als CGI läuft, funktioniert das allerdings nicht[*].

Es ist eigentlich ganz einfach, eine solche Datei muß vom Prinzip her so aussehen:

<?php
  if($PHP_AUTH_USER!="Christoph" OR $PHP_AUTH_PW!="Reeg") {
    Header('HTTP/1.1 401 Unauthorized');
    Header('WWW-Authenticate: Basic realm="Top Secret"');
    echo "Mit Abbrechen kommst Du hier nicht rein. ;-) \n";
    exit;
  }
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
 <title>Authentification</title>
</head>
<body>
<h1>Hier ist der Top-Secret Bereich</h1>
<h2><?php
  echo "Username: ".$PHP_AUTH_USER." Paßwort: ".$PHP_AUTH_PW; 
?></h2>
</body>
</html>
Das Funktionsprinzip ist ganz einfach: Beim ersten Aufruf sind die beiden Variablen ` PHP_AUTH_USER` und `PHP_AUTH_PW` nicht gesetzt. Dadurch wird der Bereich in der IF-Abfrage bearbeitet. Hier werden die beiden Header zurückgegeben, die den Browser veranlassen, nach Usernamen und Paßwort zu fragen. Diese beiden Zeilen müssen fast genau so übernommen werden, damit es funktioniert![*]Das einzige, was geändert werden darf, ist das `Top Secret`. Der Text danach wird nur dann ausgegeben, wenn jemand bei der Paßwortabfrage auf ,Abbrechen` klickt (oder, im Falle des Internet Explorers, drei Versuche, sich zu authentifizieren, mißlungen sind); dann springt der Webserver nach dem `echo` aus der Datei und der Rest wird nicht mehr ausgegeben. Wenn jedoch jemand das richtige Paßwort mit dem richtigen Usernamen eingegeben hat, wird der Bereich in der IF-Abfrage nicht bearbeitet und der Rest der Datei wird abgearbeitet. In unserem Fall wird die Überschrift ,,Hier ist der Top-Secret Bereich`` und die Zeile ,,Username: Christoph Paßwort: Reeg`` im HTML-Format ausgegeben.

Es gibt noch ein kleines Sicherheitsproblem bei der ganzen Sache - der Browser behält sich nämlich den Usernamen und das Paßwort, so daß die Autoren derjenigen Seiten, die man nach der Paßworteingabe abruft, theoretisch das Paßwort abfragen könnten. Dies kann man jedoch ganz einfach verhindern, indem man den Browser komplett beendet.

Auf fast dieselbe Weise kann man sich natürlich auch direkt für den Zugriff auf eine Datenbank authentifizieren. Der folgende Quelltext zeigt, wie man dies erreicht:

<?php
if ($PHP_AUTH_USER == "" 
      OR !@mysql_connect("localhost",$PHP_AUTH_USER,$PHP_AUTH_PW)) {
    Header('HTTP/1.0 401 Unauthorized');
    Header('WWW-Authenticate: Basic realm="Top Secret"');
    echo "Mit Abbrechen kommst Du hier nicht rein. ;-)\n";
    exit;
 }
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
 <title>Authentification</title>
</head>
<body>
<h1>Hier ist der Top-Secret Bereich</h1>
<h2><?php
  echo "Username: ".$PHP_AUTH_USER." Paßwort: ".$PHP_AUTH_PW; 
?></h2>
</body>
</html>
Das `@`-Zeichen vor dem mysql_connect hat nichts mit der if-Abfrage zu tun. Es sorgt dafür, daß keine Fehlermeldung beim Aufrauf von mysql_connect ausgegeben wird. Die Fehlermeldung würde nicht nur stören, sondern sie würde auch die Paßwortabfrage zuverlässig verhindern. Vor dem header-Aufruf darf nichts ausgegeben werden.

Der Bereich in der obigen IF-Abfrage wird genau dann nicht bearbeitet, wenn mittels Benutzername und Paßwort eine Verbindung zur Datenbank aufgebaut werden konnte. In jedem anderen Fall wird, wie im ersten Beispiel, abgebrochen und (in diesem Fall) der Text ,,Mit Abbrechen...`` ausgegeben. Um sich Probleme zu ersparen, sollte man obige Bedingung der IF-Anweisung einfach 1:1 ubernehmen, denn diese ist bestens erprobt! :-)

Noch eine Anmerkung zum Schluß: Anstatt der Zeichenkette ``HTTP/1.0 401 Unauthorized`` kann auch ``Status: 401 Unauthorized`` benutzt werden. Im Falle des o.g. PHP-CGI-Problems scheint es dann so, als ob die Authentification funktionieren würde (es tritt kein Fehler 500 mehr auf); dies ist jedoch ein Trugschluß, denn trotz allem werden die beiden benötigten Authentifizierungs-Variablen nicht mit den Werten gefüllt, die der Browser nach der Eingabe durch den Benutzer im entsprechenden Dialog zurückliefert.


next up previous contents index
Next: Reguläre Ausdrücke Up: Einführung PHP Previous: PHP & mySQL
Christoph Reeg(http://reeg.net/)