Am Ende der Seite finden Sie das komplette Beispiel als Download.
Systemvoraussetzung
- Linux
- Windows
- PHP 3
- PHP 4
- PHP 5
Datei(en)
ffbl_beispiel_sichere_seite.php,
ffbl_beispiel_login_und_logout_seite.php,
Verzeichnisusers
Problem
Ohne Datenbanken geht heutzutage fast gar nichts mehr. Dennoch wollen
auch Leute ohne Zugriff auf eine Datenbank eine Möglichkeit finden, gewisse
Dinge zu erledigen. So wäre z. B. ein Loginsystem möglich, um einen weiteren
Dateidownload zu kontrollieren. Denkbar wäre auch eine Sammlung von
Dateien nur für eine bestimmte Person.
Lösung
Das nachfolgende Beispiel ist ein Lösungsansatz von Daniel Kressler. Daniel
ist bei SELFPHP nicht mehr wegzudenken. Er hat hier eine Variante erstellt, die
Gedankenanstöße geben soll, wie man das File-System
nutzen kann.
Das „FlatFile Based Login System“ bietet Usern, die keinen Zugriff auf eine
Datenbank wie MySQL haben, die Möglichkeit, einen passwortgeschützten
Bereich einzurichten.
Es gibt viele Möglichkeiten, wie man ohne Datenbank einen solchen Bereich
realisieren kann, jedoch muss man bei einem dateibasierten System immer
auf eines achten: die Geschwindigkeit, die hier eines der größten Probleme
darstellt.
Wie könnte also ein dateibasiertes Login-Script
aussehen, das auch mit Userzahlen
jenseits der 10000 klarkommt? Man braucht für ein solches System
eine wohl durchdachte Struktur, sie ist der Schlüssel zum Erfolg.
Da die Daten in einer Datei gespeichert werden und nicht in einer komfortablen
Datenbank, könnte der Aufbau für eine solche Datei wie folgt aussehen:
- UserID
- UserName
- UserPasswort (MD5)
- UserGroupID
Dateiinhalt:
0
Daniel Kressler
e10adc3949ba59abbe56e057f20f883e
2 |
Der Dateiname setzt sich aus einem Teil oder zwei Teilen zusammen:
- Teil Username
- Optionale Dateiendung
Beispielsweise:
Für jeden User müsste eine solche Datei angelegt werden. Vor dem Anlegen der
Datei muss eine entsprechende Überprüfung stattfinden, damit kein Username
doppelt möglich ist. Mit einer derart strukturierten Datei hat man den großen
Vorteil, dass im PHP-Code
nicht eine Schleife gebraucht wird, und zwar weder
für das Login noch für das Anlegen eines neuen Users.
Auf den Registierungsvorgang wird hier nicht näher eingegangen, da dieser
mit einfachen Dateioperationen erledigt werden kann. Außerdem liegt der Sinn
dieses Beitrags nur darin, eine Möglichkeit der dateibasierten Userverwaltung
vorzustellen. Hier im Buch finden Sie bereits fertige Beispiele, um eine solche
Datei zu erstellen bzw. den MD5-Hash
zu bilden.
Warum wird keine Schleife benötigt?
Nachdem der User seine Daten (Username/Passwort) im Login-Formular
eingegeben
und dieses gesendet hat, kann man daraus ganz einfach den Dateinamen
erstellen. Der Username wird vorsichtshalber mit rawurlencode() maskiert,
so dass keine Konflikte mit dem Dateisystem selbst auftreten können, wegen
eventuell ungültiger Zeichen im Dateinamen.
Nun kann man noch eine Dateiendung anhängen, was aber keine Pflicht ist.
Sollte man die User-Dateien
in einem Unterverzeichnis hosten – das bietet sich
allein aus Übersichtsgründen an –, so muss der Pfad zu diesem Verzeichnis
ebenfalls mit berücksichtigt werden. Der Dateiname wird an den Dateipfad angehängt. Der sich so ergebende String ist ideales Futter für die Funktion
file_exists().
Liefert file_exists() FALSE zurück, dann gibt es den User nicht oder der
User hat sich bei der Eingabe verschrieben. Liefert file_exists() hingegen
TRUE zurück, kann man die Datei öffnen und anhand des in der Datei gespeicherten
MD5-Hashs
diesen mit dem nach der Usereingabe (über das Formular)
erstellten Hash vergleichen. Ergibt sich dabei eine Übereinstimmung, kann
man alle weiteren Schritte einleiten, um den User einzuloggen.
Wir werden uns jetzt dem Programmcode widmen und uns anschauen, wie der
ganze Mechanismus für diese Problemstellung eigentlich funktioniert.
Wir möchten bei diesem Programm nicht nur die Möglichkeit eines Logins
geben, sondern auch die eines Logouts. Sollte sich ein bereits eingeloggter
User wieder ausloggen wollen, werden alle Sessiondaten (35)
gelöscht. Somit
ist der Besucher ausgeloggt und vom System abgemeldet.
Wenn sich allerdings der Besucher einloggt, also seinen Usernamen und sein
Passwort eingegeben hat, wird zuerst der mögliche Dateiname inkl. Pfad anhand
des Usernamens zusammengesetzt (13). Da der Username eventuelle
Leerzeichen beinhalten kann, wird er an dieser Stelle mit rawurlencode()
kodiert. Nachfolgend sehen Sie eine mögliche Kombination aus Pfad und
Dateiname.
./users/Daniel%20Kresslere.txt |
Wir prüfen im nächsten Schritt, ob der erstelle Dateiname in unserem Ordner
existiert (15). Wurde eine Datei gefunden, so können wir mit Sicherheit sagen,
dass es den User gibt. Das nachfolgende Array mit den Benutzernamen (18-20)
dient hier der Anschauung, also was z. B. mit diesem Programm noch angezeigt
werden könnte.
Wir müssen allerdings erst überprüfen, ob der angemeldete User sein Passwort
richtig eingegeben hat. Wir öffnen also seine Datei und lesen den Inhalt
zeilenweise in ein Array ein (22).
Sollte das Passwort nicht mit dem Passwort aus der Datei übereinstimmen
(25), laden wir die aktuelle Seite neu (29) und geben eine Fehlermeldung aus.
Da wir das Passwort in der Datei verschlüsselt vorliegen haben, müssen wir
selbstverständlich auch das gelieferte Passwort verschlüsseln und beide Werte
miteinander vergleichen.
Wurde das Passwort richtig eingegeben, können wir die Daten aus der Datei
in unsere jeweiligen Session-Daten
speichern (36-47).
Das Array mit den
Userdaten enthält dabei folgende Werte:
- uid die User-ID
- uname der Username
- ugid die Usergroup-ID
- ug den Namen für die Usergroup (Zeile 18-20)
Wir haben jetzt alle Informationen gesammelt und können nun die neue Seite
(49) laden oder einen Download starten. An dieser Stelle ist es Ihnen erst
einmal selbst überlassen, wie Sie weiter verfahren wollen.
001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: 015: 016: 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: 035: 036: 037: 038: 039: 040: 041: 042: 043: 044: 045: 046: 047: 048: 049: 050: 051: 052: 053: 054: 055: 056: 057: 058: |
<?php if($_GET['action'] == 'logout'){ session_start(); session_unset(); session_destroy(); }
if(isset($_POST['login'])){
// Den Dateinamen zusammenbauen und dem Pfad anhaengen. // Das Ergebnis koennte so aussehen: // "./users/Daniel%20Kresslere.txt" $filepath = './users/' . rawurlencode($_POST['username']) . '.txt';
if(file_exists($filepath)){
// Array mit Userguppen $usergroups = array(0 => 'Normale User', 1 => 'Mitwirkende', 2 => 'Administratoren');
$userdata = file($filepath);
// $userdata[2] enthaelt den Passwort-Hash if(trim($userdata[2]) != md5($_POST['password'])){
// Hier verweigern Sie den Zutritt.
header('location: ' . $_SERVER['PHP_SELF'] . '?error');
exit(); }
session_start();
// $userdata[0] enthaelt die User ID. $_SESSION['uid'] = trim($userdata[0]);
// $userdata[1] enthaelt den Username. $_SESSION['uname'] = trim($userdata[1]);
// $userdata[3] enthaelt die Usergroup ID. $_SESSION['ugid'] = $userdata[3]; // Mit der Usergroup ID kann man das betreffende // Element im Array "$usergroups" selektieren. $_SESSION['ug'] = $usergroups[$userdata[3]];
header('location: ffbl_beispiel_sichere_seite.php?' . SID); }else{
// Hier verweigern Sie den Zutritt ebenfalls.
header('location: ' . $_SERVER['PHP_SELF'] . '?error'); }
}else{
?>
|
Beispiel 7.10: ffbl_beispiel_login_und_logout_seite.php
Sie sehen hier den else-Zweig
der vorangegangenen Programmcodes. Da er
selbsterklärend ist und hauptsächlich aus HTML- und
CSS-Definitionen
besteht,
jedoch hier nicht fehlen sollte, sollte dieser Teil keinerlei Probleme für Sie
bereiten. 059: 060: 061: 062: 063: 064: 065: 066: 067: 068: 069: 070: 071: 072: 073: 074: 075: 076: 077: 078: 079: 080: 081: 082: 083: 084: 085: 086: 087: 088: 089: 090: 091: 092: 093: 094: 095: 096: 097: 098: 099: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160:
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html> <head> <title> FBL-System </title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <style type="text/css" media="screen"> <!-- table{ font-family: arial, sans-serif; } .container{ width: 100%; text-align: center; } .loginform{ border-width: 10px; border-style: solid; border-color: #EEEEEE; background-color: #FFFFE0; } .vxhtml{ border-width: 0px; height: 31px; width: 88px; } --> </style> </head> <body> <table class="container"> <tr> <td>
<table cellpadding="0" cellspacing="0"> <tr> <td> FBL-System<br /> <br /> </td> </tr> </table> <?php // Im Falle einer Falschen Eingabe if(isset($_GET['error'])){ ?> <table cellpadding="0" cellspacing="0"> <tr> <td> Die eingegebenen Daten sind falsch! </td> </tr> </table> <?php } ?> <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <table class="loginform" cellpadding="10" cellspacing="0"> <tr> <td> Test Username:<br> Test Passwort: </td> <td> USER<br> TEST<br> </td> </tr> <tr> <td> Username: </td> <td> <input type="text" name="username" size="20" /> </td> </tr> <tr> <td> Passwort: </td> <td> <input type="password" name="password" size="20" /> </td> </tr> <tr> <td> <input type="submit" name="login" value="Login"/> </td> </tr> </table> </form> <p> <a href="http://validator.w3.org/check?uri=referer"> <img src="http://www.w3.org/Icons/valid-xhtml11" alt="Valid XHTML 1.1!" class="vxhtml" /></a> </p> </td> </tr> </table> </body> </html> <?php } ?>
|
Beispiel 7.11: ffbl_beispiel_login_und_logout_seite.php
Der nachfolgende Programmcode ist die Seite, die aufgerufen wird, wenn ein
User sich richtig, also mit korrektem Usernamen und Passwort, angemeldet
hat. Die Seite ist ebenfalls selbsterklärend, daher werden wir auch nur auf zwei
Bereiche ein wenig näher eingehen.
Der eingeloggte User bekommt im Erfolgsfall eine Session-ID
zugeteilt, die wir
hier lediglich abfragen und, falls existent, als registrierten User sehen (60). Sie
sollten an dieser Stelle allerdings noch einmal eine Überprüfung durchführen
und sich nicht alleine auf die Session-ID
verlassen!
Ein nochmaliges Einlesen der Datei mit Überprüfung des Passworts, das Sie
auch als Session-Variable
speichern könnten, wie Sie es aus dem vorangegangenen
Beispiel kennen, wäre hier sinnvoll.
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
63:
64: 65: 66: 67: 68: 69: 70: 71: 72:
73:
74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98:
|
<?PHP session_start(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html> <head> <title> FBL-System </title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<style type="text/css" media="screen"> <!-- a:link{ color: #AA5522; text-decoration: underline; } a:visited{ color: #772200; text-decoration: underline; } a:active{ color: #000000; text-decoration: none; } table{ font-family: arial, sans-serif; } .container{ width: 100%; text-align: center; } .output{ text-align: left; border-width: 10px; border-style: solid; border-color: #EEEEEE; background-color: #FFFFE0; } .vxhtml{ border-width: 0px; height: 31px; width: 88px; } --> </style> </head> <body> <table class="container"> <tr> <td> <table class="output" cellpadding="0" cellspacing="0"> <tr> <td> <?php
// UserID vorhanden, dann Login if(!empty($_SESSION['uid'])){ ?> <br /> Willkommen im sicheren Bereich
<?php echo $_SESSION['uname']; ?>!<br /> <br /> <br /> Deine Daten sind...<br /> <br /> User ID: <?php echo $_SESSION['uid']; ?><br /> Usergroup ID: <?php echo $_SESSION['ugid']; ?><br /> Groupname: <?php echo $_SESSION['ug']; ?><br /> <br /> <br /> <a href="ffbl_beispiel_login_und_logout_seite.php?action=logout&
<?php echo SID; ?>">Logout</a><br /> <br /> <?php
// Keine UserId vorhanden? Dann: // "Du kommst hier net rein!" }else{ ?> <br /> Du bist nicht eingeloggt!<br /> <br /> <a href="ffbl_beispiel_login_und_logout_seite.php">Login</a><br /> <br /> <?php } ?> </td> </tr> </table> <p> <a href="http://validator.w3.org/check?uri=referer"> <img src="http://www.w3.org/Icons/valid-xhtml11" alt="Valid XHTML 1.1!" class="vxhtml" /> </a> </p> </td> </tr> </table> </body> </html>
|
Beispiel 7.12: ffbl_beispiel_sichere_seite.php
Sie sollten allerdings das Verzeichnis users besonders schützen, indem Sie
z. B. eine .htaccessDatei
erstellen und folgenden Code hineinschreiben. Somit
kann nicht mehr auf Dateien mit der Endung .txt direkt zugegriffen werden.
<Files "*.txt">
Order allow,deny
Deny from all
</Files> |
Eine weitere Möglichkeit des Schutzes ist das Programm „Passwortschutz für
Verzeichnisse“, das Sie in einem späteren Kapitel finden.

Dieses Skript aus dem SELFPHP KOCHBUCH wurde von SELFPHP unter dem "Tarif Mc500" von McAc.net-Webhosting erfolgreich ausgeführt und getestet!
Auf der Übersichtseite unter "McAc.net – Webhosting zu diesem Buch" finden Sie weitere Informationen zu dem Webhostingpaket, dass durch SELFPHP getestet wurde.
Download
|
Alle Beispiele als PHP-Datei(en)
Hier haben Sie die Möglichkeit, sich sämtliche auf dieser Seite gezeigten Beispiele als PHP-Dateien direkt downzuloaden.
Umständliches Copy & Paste ist daher nicht mehr notwendig, da alle Beispiele sofort ausprobiert werden können.
Sie haben bei der Auswahl der bereitgestellten Downloads mehrere Möglichkeiten, je nachdem welches Komprimierungsverfahren Sie bevorzugen.
|
Zurück zur Übersichtsseite
|