| #include <pronix.de> |
|
|
27.8. Das HTTP-Protokoll
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Protokoll | Port |
| FTP (Datenverbindung) | 20 |
| FTP (Steuerverbindung) | 21 |
| Telnet | 23 |
| SMTP | 25 |
| DNS | 53 |
| http | 80 |
| HTTPS (SSL-verschlüsselt) | 443 |
| POP3 | 110 |
| NNTP | 119 |
| LDAP (Standard) | 389 |
| LDAP (SSL-verschlüsselt) | 636 |
/cgi/name.cgi (Pfadangabe)
Damit wird der Ort des gespeicherten Dokuments auf dem Webserver bezeichnet.
?vorname=Clint&nachname=East (Query-String)
Der Query-String kann aus mehreren Paaren von Namen und den dazugehörenden Werten bestehen. Die einzelnen Paare werden mit dem Zeichen & voneinander getrennt. Die Variable und der Wert werden mit einem = getrennt. In diesem Beispiel haben Sie folgende zwei Paare:
Variable des ersten Paars: vorname; Wert des ersten Paars: Clint Variable des zweiten Paars: nachname;Wert des zweiten Paars: East
Der Query-String wird noch ausführlicher behandelt.
27.8.7 Client-Anfrage - HTTP Request (Browser-Request)
Das Erste bei einer HTTP-Verbindung ist immer die Anfrage (HTTP-Request) des Webbrowsers an den Webserver. Geben Sie beispielsweise in Ihrem Browser folgende URL ein
http://www.pronix.de/
und drücken ENTER, schickt der Browser eine Anfrage an den Webserver, die aus zwei Teilen besteht. Zum einen Teil aus der Anforderungszeile und zum anderen aus den Header-Feldern:
GET /index.html HTTP/1.1 Host: www.pronix.de Accept: image/gif, image/jpeg, image/pjpeg, */* Accept-Language: de Connection: Keep-Alive User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Referer: … …
Die erste Zeile ist die so genannte Request-Zeile:
GET /index.html HTTP/1.1
GET ist dabei die Request-Methode, mit der eine Ressource vom Server angefordert wird, ohne dass dabei irgendwelche Daten auf dem Server verändert werden. GET ist die Standard-Methode, wenn ein Browser per HTTP ein Dokument anfordert. In diesem Beispiel wird die Datei index.html angefordert. Das Protokoll, durch das der Webbrowser und der Webserver sich unterhalten sollen, ist hier HTTP mit der Versionsnummer 1.1.
Eine andere häufig verwendete Request-Methode ist POST. Im Wesentlichen unterscheiden sich diese beiden Methoden zur Datenübermittlung in der Art, wie die Daten an den Webserver übergeben werden.
Um Ihnen den Unterschied zwischen den beiden Request-Methoden GET und POST etwas deutlicher zu machen, folgt hier eine kurze theoretische Beschreibung.
GET
Hier soll bei einem HTML-Formular einfach die Eingabe eines Textfeldes ausgewertet werden. Ich verwende hierfür folgenden HTML-Code:
<form action="http://localhost/cgi-bin/auswert.cgi" method=get> <b>Bitte geben Sie Ihren Namen ein : </b> <input value="hallo" name="Textfeld" size="20"> <input type=submit value="abschicken"> </form>
Dadurch entsteht das folgende Textfeld mit einem Button:

Abbildung 27.10: Eingabefeld mit Button
Mit der Zeile
<form action="http://localhost/cgi-bin/auswert.cgi" method=get>
fordern Sie das CGI-Programm auswert.cgi mit der Methode GET (method=get) an. Dabei können Sie auch gleich sehen, wie Sie die Methode des HTTP-Requests bestimmen können. Beim Drücken des Buttons wird die CGI-Anwendung auf dem Server aufgerufen. Ein Blick auf die URL des Webbrowsers zeigt Folgendes:
http://localhost/cgi-bin/auswert.cgi?Textfeld=hallo
Den Query-String können Sie jetzt auf dem Webserver mit der CGI-Anwendung auswert.cgi aus der gleichnamigen Umgebungsvariablen QUERY_STRING auslesen. In dieser Variablen befindet sich jetzt folgender String:
QUERY_STRING= Textfeld=hallo
POST
Wollen Sie das Gleiche mit der POST-Methode machen, müssen Sie nur Folgendes im HTML-Code umändern:
<form action="http://localhost/cgi-bin/auswert.cgi" method=post>
Jetzt befindet sich in der URL, bei Klicken des Buttons, kein Query-String mehr. In diesem Beispiel müssen Sie die Umgebungsvariable CONTENT_LENGTH nach der Anzahl der Bytes, die diese Nachricht enthält, abfragen. Anschließend können Sie CONTENT_LENGTH Bytes von der Standardeingabe (stdin) einlesen. Zum Beispiel mit fgets():
fgets(puffer, CONTENT_LENGTH, stdin);
Danach befindet sich die komplette Eingabe (Textfeld=IhrName) vom HTML-Formular im String puffer.
Sowohl bei der Methode GET als auch bei der POST-Methode liegen die Daten kodiert vor und müssen noch dekodiert werden. Wie das geht, erfahren Sie in Kürze.
Weitere Methoden
Es gibt noch einige weitere Methoden, auf die hier aber nicht eingegangen wird. Diese Methoden werden in der Praxis kaum eingesetzt. Hier nur ein schneller Überblick zu den weiteren möglichen Anforderungen, die Sie an den Webserver stellen könnten:
Request Header
Außer der Request-Zeile schickt der Browser dem Webserver noch einige Informationen, den so genannten Request-Header mit. Diese Informationen bestehen aus dem Feldnamen, vom Wert mit einem Doppelpunkt getrennt. Dazu nochmals zur Erinnerung das Beispiel eines HTTP-Request, welches Sie weiter oben schon gesehen haben:
GET /index.html HTTP/1.1 Host: www.pronix.de Accept: image/gif, image/jpeg, image/pjpeg, */* Accept-Language: de Connection: Keep-Alive User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Referer: …
In diesem Beispiel ist das Fettgedruckte der Request-Header.
In der folgenden Tabelle finden Sie einen Überblick zu einigen HTTP-Request-Headern. Diese Informationen schicken Sie praktisch immer mit, wenn Sie mit einem Webbrowser unterwegs sind und eine neue Webseite vom Webserver anfordern.
| Request-Header | Bedeutung |
| Host | Der Host ist der Zielrechner, auf dem sich das angeforderte Dokument befindet. |
| Content-Length | Damit der Server weiß, wie viele Daten er aus dem Nachrichten-Body des HTTP-Requests lesen soll, wird dieser Header verwendet. Natürlich gilt dies nur für den POST-Request (siehe POST). Bei einer Anforderung mit der Methode GET wird dieses Feld nicht mit angegeben. |
| Content-Type | Besitzt ein Request einen Nachrichten-Body, muss der Content-Type-Header mitgeschickt werden. Damit wird der Medientyp des Nachrichten-Body angegeben. |
| User-Agent | Darin befinden sich Angaben darüber, mit welchem Webbrowser und Betriebssystem die Anfrage vorgenommen wurde. Wobei diese Angaben nicht immer stimmen müssen. Viele Programme und auch Webbrowser bieten eine Option an, diesen Header zu manipulieren. |
| Referer | Darin befindet sich in der Regel die URL, welche der Anwender zuletzt besucht hat. Wenn der User aber eine URL direkt in den Webbrowser oder ein Bookmark verwendet, befindet sich nichts in diesem Header. |
| Accept | Es gibt mehrere Accept-Header. Darin schickt der Browser dem Server Daten, welche Arten von Response (Antworten vom Server) er verstehen kann. Zum Beispiel:Accept: Liste der Medientypen, die der Browser (Client) akzeptiert.Accept-Charset: Liste der Zeichensätze, die der Browser akzeptiert.Accept-Language: Sprachen, die der Browser akzeptiert. |
| Cookies | Damit teilt der Browser dem Server mit, ob dieser Cookies akzeptiert. Deaktivieren Sie zum Beispiel in Ihrem Browser die Cookies, so wird dieser Header nicht mitgeschickt. Der Server kann, falls Cookies akzeptiert werden, ein Cookie setzen. |
27.8.8 Serverantwort (Server-Response)
Nachdem Sie einen HTTP-Request des Webbrowsers ausführlich durchgearbeitet haben, wird Ihnen der Webserver auch irgendwann mit einer HTTP-Response antworten.
Die Antwort besteht aus einer Statuszeile, ebenfalls aus einigen Header-Feldern und häufig auch aus einem Nachrichten-Body. Hierzu ein Antwort-Beispiel des Webservers:
HTTP/1.1 200 OK Date: Wed, 30 Oct 2002 01:21:22 GMT Server: Apache/1.3.14 Last Modified: Tue, 29 Oct 2002 22:21:19 GMT Content-Length: 2232 Content-Type: text/html <html> … … </html>
Der Statuscode
In der ersten Zeile, der Statuszeile, wird außer dem Protokoll mit der Versionsnummer ein dreistelliger Statuscode angegeben.
HTTP/1.1 200 OK
Anhand dieses Statuscodes bekommt der Webbrowser die Antwort auf seine Anforderung. In diesem Beispiel wird der Statuscode 200 zurückgegeben, was einem erfolgreichen Request vorangeht. Recht häufig dürfte Ihnen der Statuscode 404 im Internet begegnet sein. Dieser wird zurückgegeben, wenn das angeforderte Dokument nicht gefunden wurde.
Hierzu folgt ein Überblick der möglichen Statuscodes. Zuerst eine Tabelle der fünf Gruppen von Codes, die anhand der ersten Ziffer unterschieden werden:
| Statusbereich | Bedeutung |
| 200-299 | Alles in Ordnung. |
| 300-399 | Veränderungsstatus, Verlagerungen, weitere Maßnamen müssen getroffen werden. |
| 400-499 | Fehlermeldung vom Client (meistens Webbrowser). |
| 500-599 | Fehlermeldung vom Server. |
Dazu noch eine Tabelle, mit denen in der Praxis etwas häufiger auftretenden Statuscodes und ihren Bedeutungen:
| Statuscode | Bedeutung |
| 200 | Alles OK. |
| 201 | POST-Befehl erfolgreich. |
| 202 | Anforderung akzeptiert. |
| 203 | GET-Anforderung erfüllt. |
| 204 | Anforderung erfüllt, aber Rücksendung nicht verstanden. |
| 300 | Datenquelle an mehreren Stellen gefunden. |
| 301 | Datenquelle war dauernd in Bewegung. |
| 302 | Datenquelle war zeitweise in Bewegung. |
| 304 | Datenquelle konnte nicht näher bestimmt werden. |
| 400 | Unverständliche Anforderung vom Client. |
| 401 | Ein File wurde angefragt, für den sich der User ausweisen muss. |
| 403 | Anfrage war verständlich, der Server weigert sich jedoch, das Dokument zu senden, da dieser oder der Client keine Berechtigung haben. Beispiel: keine Leserechte der Datei. |
| 404 | Datenquelle nicht gefunden. |
| 405 | Verfahren an Datenquelle nicht erlaubt. Z.B. die Abfrage-Methode POST ist explizit gesperrt. |
| 406 | Art der Datenquelle nicht erwünscht. |
| 408 | Anfrage Timeout ->Server überlastet? Fehlkonfiguriert? |
| 500 | Fehler im CGI-Skript, falsche Zugriffsrechte, Server falsch konfiguriert. |
| 501 | Anfrage wird vom Server nicht unterstützt, da notwendige Module nicht implementiert. |
| 502 | Schlechte Netzverbindung oder Server überladen. |
| 503 | Dienst steht nicht zur Verfügung - Timeout, wenn z.B. ein Datenbankserver nicht reagiert. |
Server-Header
Es folgt eine kurze Beschreibung der gängigsten HTTP-Server-Header, die der Webserver dem Webbrowser sendet.
| Server-Header | Bedeutung |
| Date | Datum und Uhrzeit, wann die Antwort geschickt wurde. |
| Server | Name und Versionsnummer des Webservers. |
| Content-Length | Länge des Nachrichten-Body in Bytes. |
| Content-Type | Art des Dokuments im Nachrichten-Body. text/html steht beispielsweise für eine HTML-Datei. Geben Sie dafür hingegen text/plain an, dann handelt es sich um eine reine Textdatei. Dieser Header wird bei fast allen CGI-Anwendungen benötigt, die einen Nachrichten-Body besitzen. |
| Last Modified | Datum der letzen Änderung des angeforderten Dokuments. |
| Set-Cookie | Damit können Sie ein Cookie setzen. |
| Location | Speicherort des Dokuments. |
27.8.9 Zusammenfassung
Jetzt haben Sie mit dem HTTP-Protokoll das schwierigste und wahrscheinlich auch langweiligste Kapitel hinter sich. Im Laufe der nächsten Seiten wird Ihnen einiges, was Ihnen vielleicht noch nicht so klar ist, in einem anderen Licht erscheinen. Speziell in den nächsten Abschnitten werden Sie sehen, wie Sie mit CGI-Anwendungen und dem HTTP-Webserver zusammenarbeiten können, um dynamische Webseiten zu erstellen.
Damit Sie CGI-Anwendungen auf einem Server ausführen können, muss dafür eine bestimmte Umgebung erzeugt werden. CGI erzeugt diese Umgebung. In diesem Abschnitt geht es darum, welche Umgebung Ihnen CGI zur Verfügung stellt und wie Sie damit arbeiten können.
27.9.1 Filehandles
Den Standard-Filehandles stdin und stdout fällt bei CGI-Anwendungen eine besondere Rolle zu.
Einfacher geht es eigentlich kaum. Daten vom Webbrowser für die CGI-Anwendung werden einfach über die Standardeingabe (stdin) eingelesen, und Daten für den Webbrowser (z.B. die Darstellung einer Webseite) werden über die Standardausgabe (stdout) ausgegeben. Und hier greifen Sie ein. Sie sind mit einer dazwischen liegenden CGI-Anwendung verantwortlich für den Datenfluss.
Was die Standardfehlerausgabe (stderr) bei CGI-Anwendungen macht, ist nicht festgelegt und somit abhängig von den einzelnen Webservern.
Zumindest beim Apache werden Ausgaben in das in der httpd.conf angegebene error.log geleitet.
27.9.2 CGI-Umgebungsvariablen
In den so genannten Umgebungsvariablen befinden sich Informationen zum Webserver und zum Client (Browser). Die CGI-Umgebungsvariablen werden aus drei verschiedenen Quellen erzeugt:
Einige der Umgebungsvariablen werden dabei aus einer Kombination dieser drei Quellen gesetzt. Hier folgt ein Überblick zu einigen Standard-Umgebungsvariablen auf dem Webserver:
| CGI-Umgebungsvariable | Bedeutung |
| AUTH_TYPE | Authentifizierungsmethode zur Überprüfung des Benutzers (falls angefordert). |
| CONTENT_LENGTH | Größe der Daten in Bytes, die an die Standardeingabe (stdin) der CGI-Anwendung übergeben wurden. |
| CONTENT_TYPE | Die Art des Dokuments des Nachrichten-Body. |
| DOCUMENT_ROOT | Verzeichnis, aus dem statische Webseiten gelesen werden. |
| GATEWAY_INTERFACE | Version der CGI-Spezifikation des Webservers. |
| PATH_INFO | Zusätzliche Pfadinformationen, die beispielsweise vom Webbrowser übergeben wurden. |
| PATH_TRANSLATED | Die übersetzte Version von PATH_INFO, die als Systempfad angegeben wird. |
| QUERY_STRING | Die Information, die mit einem ? an die URL gehängt wird. |
| REMOTE_ADDR | Die IP-Adresse des Clients, der den Request geschickt hat. |
| REMOTE_HOST | Der DNS-Name des Clients, der den Request geschickt hat. |
| REMOTE_IDENT | Name des Remote-Benutzers, der vom Server ermittelt wurde. Funktioniert nur, wenn Server und Client die RFC 931-Identifikation unterstützen. |
| REMOTE_USER | Unterstützt Ihr Server Benutzer-Authentifizierung, ist dies der Benutzername, mit dem Sie sich authentifiziert haben. |
| REQUEST_METHOD | Die Methode der verwendeten HTTP-Anfrage (meist GET oder POST). |
| SCRIPT_NAME | URL-Pfad des ausgeführten Skripts. |
| SERVER_NAME | Der Hostname, der DNS-Alias oder die IP-Adresse des Serverrechners. |
| SERVER_PORT | Portnummer, an die die HTTP-Anfrage gesendet wurde. Meistens Port 80. |
| SERVER_PROTOCOL | Name und Versionsnummer des Protokolls, mit dem die Anfrage gesendet wurde. |
| SERVER_SOFTWARE | Name und Versionsnummer des verwendeten Webservers. |
Weitere Header-Variablen, die Ihnen Apache zur Verfügung stellt, sind die vom Client (Webbrowser) bei der Anfrage gesendeten Variablen. Alle diese Header-Variablen sind gleich aufgebaut: HTTP_Name_des_Headers. Hierzu einige dieser Variablen im Überblick:
| Header-Variablen | Bedeutung |
| HTTP_ACCEPT | Liste der akzeptierten Medientypen. |
| HTTP_ACCEPT_CHARSET | Liste der akzeptierten Zeichensätze. |
| HTTP_ACCEPT_LANGUAGE | Liste der akzeptierten Sprachen. |
| HTTP_COOKIE | Das Cookie, das vom Server gesetzt wurde. |
| HTTP_FROM | E-Mail-Adresse des Benutzers, der den Request gesendet hat (ist meistens nicht gesetzt). |
| HTTP_REFERER | Die URL, die der Benutzer zuletzt besucht hat. Ausnahme: eine direkt eingetippte URL oder ein Bookmark. |
| HTTP_USER_AGENT | Name und Versionen des Betriebssystems und des Webbrowsers, der den Request gesendet hat. |
Um jetzt auf die Umgebungsvariablen zuzugreifen, wird die ANSI C-Funktion getenv() verwendet:
#include <stdlib.h> char *getenv(const char *str);
Ist die Umgebungsvariable str vorhanden, wird ein Zeiger auf den Inhalt dieser Umgebungsvariable zurückgegeben. Wenn die Umgebungsvariable nicht vorhanden ist, wird NULL zurückgegeben. Wollen Sie beispielsweise abfragen, von welchem Betriebssystem und welchem Webbrowser die Anfrage gestellt wurde, können Sie wie folgt vorgehen:
#include <stdio.h>
#include <stdlib.h>
/* Die Kopfzeile eines Standard-HTML-Dokuments
* titel: String, der als Titel erscheinen soll
*/
void print_html_header(char *titel)
{
printf("<html><head>\n");
printf("<title>%s</title>\n",titel);
printf("</head><body><pre>\n");
}
/* Das Ende eines HTML-Dokuments */
void print_html_end()
{
printf("</pre></body></html>\n");
}
/* Damit überhaupt ein HTML-Dokument ausgegeben wird */
void print_header()
{
printf("Content-Type: text/html\n\n");
}
int main()
{
char *p;
print_header();
print_html_header("Wer bin ich?");
p = getenv("HTTP_USER_AGENT");
if(p!=NULL)
printf("Sie browsen mit : %s\n",p);
else
printf("Konnte HTTP_USER_AGENT nicht ermitteln!\n");
print_html_end();
return 0;
}
Wenn Sie diese CGI-Anwendung wieder aufrufen (der Name sei browser.cgi), und zwar mit http://localhost/cgi-bin/browser.cgi, dann sollten Sie im Browser einen String vorfinden wie z.B.:
Sie browsen mit: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser)
oder
Sie browsen mit: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020
Die Abfrage aller Umgebungsvariablen soll jetzt in eine Funktion gepackt werden. Das folgende Listing gibt alle vorhandenen Umgebungsvariablen auf dem Browser aus:
#include <stdio.h>
#include <stdlib.h>
/* Listing gibt alle vorhandenen Environment-Variablen aus */
char *env[] =
{ "AUTH_TYPE", "CONTENT_LENGTH", "CONTENT_TYPE",
"GATEWAY_INTERFACE", "HTTP_ACCEPT", "HTTP_CONNECTION",
"HTTP_HOST", "HTTP_REFERER", "HTTP_USER_AGENT",
"PATH_INFO", "PATH_TRANSLATET", "QUERY_STRING",
"REMOTE_ADDR", "REMOTE_HOST", "REMOTE_IDENT",
"REMOTE_USER", "REQUEST_METHOD", "SCRIPT_NAME",
"SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL",
"SERVER_SOFTWARE" , NULL
};
/* Die Kopfzeile eines Standard-HTML-Dokuments
* titel: String, der als Titel erscheinen soll
*/
void print_html_header(char *titel)
{
printf("<html><head>\n");
printf("<title>%s</title>\n",titel);
printf("</head><body><pre>\n");
}
/* Das Ende eines HTML-Dokuments */
void print_html_end()
{
printf("</pre></body></html>\n");
}
/* Damit überhaupt ein HTML-Dokument ausgegeben wird */
void print_header()
{
printf("Content-Type: text/html\n\n");
}
/* Inhalt der Environment-Variable ausgeben*/
void environment(const char *s)
{
char *p;
p = getenv(s);
printf ("%s", s);
if(p!=NULL)
printf (" = %s", p);
else
printf(" = (<i>keine Angaben</i>)");
printf ("<BR>\n");
}
int main()
{
int i;
print_header();
print_html_header("CGI-Umgebungsvariablen ausgeben - 2\n");
for(i=0; env[i] != NULL; i++)
environment(env[i]);
print_html_end();
return 0;
}

Abbildung 27.xx: Ausgabe der Umgebungsvariablen
Dreh- und Angelpunkt ist die Funktion environment(), welche mit einem entsprechenden String als Argument, die, hier alle in eine Stringtabelle verpackt wurden, aufgerufen wird. Hier werden in einer Schleife alle Umgebungsvariablen abgefragt und ausgegeben.
27.9.3 CGI-Ausgabe
Wenn Ihre CGI-Anwendung etwas ausgeben soll, müssen Sie mindestens eine Headerzeile ausgeben. Der Webserver erledigt dann den Rest, wie zum Beispiel die Ausgabe weiterer Header. Von den drei folgenden Headern muss mindestens einer angegeben werden.
Content-Type-Dokumente ausgeben
Wollen Sie, dass Ihre CGI-Anwendung ein bestimmtes Dokument ausgibt, müssen Sie dem Webserver erst mitteilen, um was für ein Dokument es sich handelt. Meistens werden Sie ein HTML-Dokument ausgeben wollen. Dies wird mit folgender Angabe erledigt:
printf("Content-Type: text/html\n\n");
Die beide Newline-Zeichen am Ende sind enorm wichtig. Dabei wird dem Webserver angezeigt, dass es sich um die letzte Headerzeile handelt. Wenn der Webserver diese Leerzeile erhält, kann er dem Webbrowser seine Daten schicken. Meistens ist dies das Anzeigen einer HTML-Webseite. Natürlich lassen sich mit dem Content-Type-Header noch unzählig viele andere Dokumente neben den HTML-Dokumenten ausgeben.
Status - Statuscode ausgeben
Damit können Sie angeben, welchen Statuscode der Webserver an den Webbrowser als Response schicken soll. Welche unterschiedlichen Statuscodes Sie verwenden können, wissen Sie bereits. Wollen Sie zum Beispiel den Statuscode 403 (Forbidden) an den Webbrowser senden, und zwar derart, dass der Surfer keinen Zugriff auf diese Seite hat, können Sie so vorgehen:
printf("Status: 403");
Location - Weiterleiten an ein anderes Dokument
Wollen Sie mithilfe einer CGI-Anwendung nicht ein Dokument ausgeben, sondern auf ein anderes Dokument weiterleiten, können Sie dazu den Location-Header verwenden. Dieser lässt sich beispielsweise ideal einsetzen, wenn sich die URL eines Dokuments geändert hat. Anwenden können Sie den Header so:
printf("Location: umleitungs_ziel.html\n\n");
Bitte bedenken Sie auch, dass es immer noch Surfer mit älteren Browsern gibt, die eine automatische Weiterleitung nicht unterstützen. Schreiben Sie dafür ein paar extra Zeilen HTML-Code mit einem Link zum Weiterklicken. Hierzu folgt jetzt ein Programmbeispiel, welches Surfer mit bestimmten IP-Adressen (REMOTE_ADDR) den Zugang auf die Webseite verweigert. Falls aber die IP-Adresse Zugang hat, wird der Surfer zu einer entsprechenden URL weitergeleitet.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Listing fragt REMOTE_ADDR ab. Lässt sich der Wert nicht
auslesen, gibt das CGI-Programm den Statuscode 500 zurück.
Ansonsten werden die verbotenen IP-Adressen in forbidden mit
REMOTE_ADDR überprüft und entsprechende Maßnahmen getroffen */
/* Die Liste der IP-Adressen, welche keinen Zutritt auf der Seite
haben sollen */
char *forbidden[] = { "127.0.0.1", "168.123.6.1", NULL };
/* Weiterleitung zu einer URL
* url ist die URL, wohin Sie den User weiterleiten
*/
void print_location(char *url)
{
printf("Location: %s\n\n", url);
/* Für den Fall, dass ein alter Browser keine
automatische Weiterleitung unterstützt */
printf("Content-Type: text/html\n\n");
printf("<html><head>\n");
printf("<title>Weiterleitung zu %s</title>\n",url);
printf("</head><body><pre>\n");
printf("Weiter gehts <a href=\"%s\">hier</a>",url);
printf("</pre></body></html>\n");
}
/* Statuscode zurückgeben */
void print_status(char *status)
{
printf("Status: %s", status);
}
int main()
{
char *p;
int i;
/* IP-Adresse ermitteln */
p = getenv(?REMOTE_ADDR?);
if( p == NULL)
{ /* Fehler bei getenv-Abfrage */
print_status("500");
return 0;
}
for(i=0; forbidden[i] != NULL; i++)
if(strcmp(p, forbidden[i]) == 0)
{ /* Diese IP hat keinen Zutritt */
print_status("403");
return 0;
}
/* Ok, der User wird auf die Willkommen-Seite weitergeleitet.
Die URL auf Ihre Bedürfnisse anpassen */
print_location("http://localhost/welcome.html");
return 0;
}
Zuerst überprüft die CGI-Anwendung die IP-Adresse des Surfers. Sollte es dabei schon zu Problemen kommen, wird der Fehlercode 500 zurückgegeben, ein Serverfehler also. Ansonsten wird die Stringtabelle forbidden durchlaufen und mit strcmp() und dem Rückgabewert von getenv() verglichen. Bei der IP-Adresse 127.0.0.1 handelt es sich um die Adresse des localhost. Wenn Sie die Anwendung auf Ihrem System testen wollen, handelt es sich um Ihre eigene IP-Adresse. In diesem Fall sollten Sie den Statuscode 403 (Forbidden) vom Browser zurückbekommen. Der letze Fall leitet Sie auf die URL http://localhost/welcome.html weiter, welche sich im Beispiel im htdocs-Verzeichnis befindet.
Außerdem empfehle ich Ihnen, die Daten der Stringtabelle forbidden in einer extra Datei zu speichern. Diese Datei können Sie dann beim Ausführen der CGI-Anwendung zum Lesen öffnen, auslesen und mit REMOTE_ADDR überprüfen. Eine extra Datei ist deshalb sinnvoller, weil Sie beim Hinzufügen von weiteren IP-Adressen nicht das komplette Listing neu übersetzen müssen.
|
Hinweis |
|
In der Praxis empfiehlt es sich, die Zugriffe auf bestimmte Seiten mit der Datei .htaccess zu regeln. Dies ist wesentlich einfacher, als eine CGI-Anwendung dafür zu schreiben. |
|