Ein sessionbasiertes Loginsystem
Irgendwann kommt man an den Punkt, an dem man gerne einen Bereich mit einem Passwort schützen möchte. Die Kombination von Sessions und einer Datenbank - in diesem Fall MySQL - ist dafür prädestiniert.
Achtung:
Dieses Tutorial gewährleistet keinerlei Sicherheit des Logins. Die Verwendung der hier vorgestellten Quelltext erfolgt auf eigene Gefahr.
Aber jetzt mal zum Thema.
Wir möchten also eine geheime Seite haben, die nur per Login erreicht werden kann. Wir brauchen also auf jeden Fall mal ein Loginformular.
Fangen wir direkt einmal damit an.
Die Datei enthält keinerlei PHP-Code, da dies nicht unbedingt nötig ist. Aus diesem Grunde habe ich der Datei auch die Endung .html gegeben. Das kann natürlich je nach Bedarf geändert werden.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Loginformular</h1>
<form action="validateLogin.inc.php" method="post">
<input type="text" name="username">
<input type="password" name="passwort">
<input type="submit" name="login" value="Einloggen">
</form>
</body>
</html>
Da gibt es nicht viel zu sagen. Das Formular wird an die PHP-Datei "validateLogin.inc.php" geschickt. Diese Datei überprüft die Richtigkeit der Eingaben und leitet den User je nach Ergebnis der Überprüfung weiter.
Schauen wir uns also diese Datei etwas näher an.
Die Datei validateLogin.inc.php - das Kernstück des Logins
Hier passiert relativ viel. Da wird mit Sessions arbeiten müssen wird zunächst einmal die Session starten.
PHP-Code:
<?php
session_start();
?>
Danach überprüfen wir, ob der User die Eingaben überhaupt gemacht hat. Ist dies der Fall, so beginnt die eigentliche Validierung der Eingaben.
Unser Nutzerdaten sind in einer Datenbank gespeichert. Erst wenn wir sicher sind, dass der Nutzer die Angaben komplett gemacht hat erstellen wir eine Verbindung zur Datenbank. Dazu binden wir eine Konfigurationsdatei ein, die die Zugangsdaten zur Datenbank enthält.
Danach erstellen wir die Verbindung.
PHP-Code:
<?php
// Überprüfen, ob das Formular abgeschickt wurde und ob beide Angaben gemacht wurden.
if( isset($_POST['username'], $_POST['passwort'])
AND
strcmp(trim($_POST['username']),'') != 0
AND
strcmp(trim($_POST['passwort']),'') != 0 ) {
]
// Einbinden der Konfigurationsdatei
include_once 'config.inc.php';
// Erstellen der Verbindung zur MySQL-Datenbank
if( !$connection = mysql_connect( $_config['host'], $_config['user'], $_config['password'] ) ) {
die( 'Verbindung zum Datenbankserver konnte nicht hergestellt werden.' );
}
if( !mysql_select_db( $_config['database'], $connection ) ) {
die ( 'Die Datenbank ' . $_config['database'] . ' kann nicht verwendet werden. <br />
MySQL-Error: <br />' . mysql_error() );
}
?>
Nun schicken wir eine SQL-Anweisung an die Datenbank, die den Datensatz selektiert, der dem User entspricht, der sich gerade einloggen möchte.
Den Datensatz identifizieren wir durch die Kombination aus Usernamen und Passwort.
Das Passwort steht aus Sicherheitsgründen nicht im Klartext in der Datenbank, sondern als md5-Verschlüsselung.
PHP-Code:
<?php
// SQL-Anweisung an die Datenbank senden, um erstens herauszufinden, ob
// diese Kombination von Usernamen und Passwort überhaupt existiert und
// zweitens bei Existenz Userinformationen auszulesen
$sql = "SELECT
_id,
_anzahlLogins
FROM
archiv_login
WHERE
_username = '" . trim($_POST['username']) . "'
AND
_passwort = '" . md5(trim($_POST['passwort'])) . "'";
$res = mysql_query($sql) or die( 'Error[SELECT|User]: <br />
<pre>' . $sql . '</pre>
<br />
MySQL-Error: ' . mysql_error() );
?>
Nun ist es natürlich möglich, dass es keinen Datensatz mit der angegebenen Kombination aus Usernamen und Passwort gibt. In diesem Fall ist kein Datensatz selektiert worden.
Sollte aus unvorhersehbaren Gründen mehr als einen selektierten Datensatz geben brechen wir den Login aus Sicherheitsgründen ab.
Je nach Bedarf kann man sich für diesen Spezialfall noch etwas individuelles ausdenken.
Wir fassen nun diese beiden Fälle allerdings zusammen.
PHP-Code:
<?php
// Nur wenn genau ein Datensatz selektiert wurde wird der User eingeloggt.
// In allen anderen Fällen wird er zurück zum Loginformular geleitet.
if( mysql_num_rows($res) != 1 ) {
header( 'Location: http://localhost/loginfehler.html' );
exit();
}
?>
Der User wird also zur Datei "loginfehler.html" weitergeleitet, wenn er falsche Logindaten eingegeben hat. Auf diese Datei gehe ich später in diesem Tutorial ein, da sie nicht wirklich spannend ist ;)
Viel interessanter ist der Erfolgsfall. Der User hat sich also mit seinen richtigen Daten angemeldet. Der Login ist also erfolgreich.
In diesem Fall wird die Session mit Informationen gefüllt. Als wichtigste Handlung wird die Variale $_SESSION['loggendIn'] auf true gesetzt. So kann der User im passwortgesicherten Bereich als eingeloggt identifiziert werden.
PHP-Code:
<?php
// Der Schlüssel 'loggedIn' erhält den Wert 'true'. So kann überprüft später werden,
// ob der User eingeloggt ist oder nicht.
$_SESSION['loggedIn'] = true;
?>
Als Zusatz füllen wir die Session mit noch einigen weiteren userspezifischen Daten.
PHP-Code:
<?php
// Die userspezifischen Daten werden ausgelesen und der Session hinzugefügt
$user = mysql_fetch_object($res);
$_SESSION['anzahlLogins'] = $user->_anzahlLogins;
$_SESSION['id'] = $user->_id;
?>
Nun können wir auch direkt die Anzahl der bisherigen Logins aktualisieren und damit den Login abschließen. Dieses Feature ist natürlich optional. Ich möchte damit nur andeuten, dass diese Datei natürlich viel mehr machen kann, als nur die Logindaten zu überprüfen 
PHP-Code:
<?php
// Aktualisierung des Anzahl der Logins
$sql = 'UPDATE
archiv_login
SET
_anzahlLogins = _anzahlLogins + 1
WHERE
_id = ' . $user->_id;
mysql_query($sql) or die( 'Error[UPDATE|User]: <br />
<pre>' . $sql . '</pre>
<br />
MySQL-Error: ' . mysql_error() );
?>
Als letzte Handlung dieser Datei wird der User jetzt natürlich noch zu einer Seite im geschützten Bereich weitergeleitet.
PHP-Code:
<?php
// Der Login war erfolgreich und der User wird zur Startseite des
// passwortgeschützen Bereichs weitergeleitet
header( 'Location: http://localhost/geheim.php' );
exit();
?>
Kommen wir nun zu den restlichen Dateien, die uns noch fehlen, um ein geschlossenes System zu erhalten.
Zunächst trage ich noch die Datei "loginfehler.html" nach.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Fehler beim Login</title>
<meta http-equiv="refresh" content="5; URL=http://localhost/loginformular.html">
</head>
<body>
<h1>Es ist ein Fehler beim Login aufgetreten.</h1>
<p>Eventuell handelt es sich nur um einen Tippfehler. Bitte versuchen Sie es nochmals.</p>
Sie werden nach von 5 Sekunden automatisch weitergeleitet.
</body>
</html>
Ich denke nicht, dass ich da etwas zu sagen brauche. Die Weiterleitung erfolgt salopp gesagt per 'meta-refresh'.
Dann wurde oben natürlich schon die Datei "geheim.php" verwendet. Da wird der User nach dem Login ja hingeleitet.
Diese Datei bindet ganz zu Beginn eine weitere Datei ein.
PHP-Code:
<?php
include_once 'checkLogin.inc.php';
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"[url]http://www.w3.org/TR/html4/loose.dtd">[/url]
<html>
<head>
<title>Geheime Seite</title>
</head>
<body>
<h1>Das ist die <i>geheime</i> Seite</h1>
<p>Die Daten, die in der Session zum weiteren Gebrauch gespeichert sind:</p>
<?php
echo '<pre>';
print_r($_SESSION);
echo '</pre>';
?>
<p><a href="logout.php">Logout</a></p>
</body>
</html>
Die Datei "checkLogin.inc.php" macht nur eine einzige Sache. Sie überprüft, ob die Session-Variable $_SESSION['loggendIn'] mit true belegt ist oder nicht.
Ist dies nicht der Fall, so wird der User zum Loginformular geschickt, da er ja nicht eingeloggt ist. Somit ist sichergestellt, dass nur eingeloggte User die Seite "geheim.php" zu sehen bekommen.
Die Datei "checkLogin.inc.php" sieht somit folgendermaßen aus:
PHP-Code:
<?php
session_start();
if( !$_SESSION['loggedIn'] ) {
header( 'Location: http://localhost/loginformular.html' );
exit();
}
?>
Aber nochmal zurück zur Datei "geheim.php". In diesem Tutorial ist da natürlich nichts interessantes zu sehen. Es geht ja nur um das Prinzip. Allerdings erkennt man am Ende der Datei noch eine sehr wichtige und oft vergessene Funktionalität - den Logout.
Klickt man auf den Link, so wird die Datei "logout.php" aufgerufen
PHP-Code:
<?php
session_start();
$_SESSION['loggedIn'] = false;
header( 'Location: http://localhost/loginformular.html' );
exit();
?>
Hier entsteht nun ein Diskussionspunkt. Sollte man die Session nicht direkt komplett zerstören, z.B. per session_destroy()?
Ich persönlich sehe das nicht so. Ich setze einfach die Variable $_SESSION['loggedIn'] auf false. Dadurch wird abgesichert, dass der User nach dem Logout nicht mehr in den geschützen Bereich kann (das wird ja durch die Datei "checkLogin.inc.php" gewährleistet!) und die Session kann trotzdem noch weiterverwendet werden.
Sinnvoll wäre es natürlich alle Session-Variablen, die irgendwas mit dem geschützten Bereich zu tun haben zu löschen. Aber es können sich ja auch andere Daten in der Session befinden.
Das kann aber jeder für sich individuell entscheiden.
Ich möchte hier noch auf den nächsten Beitrag verweisen. Dort findet man noch einmal alle Dateien mit komplettem Quelltext und zusätzlich einen SQL-Export, so dass man das Tutorial direkt testen kann.
Ich denke, dass man mit diesem Tutorial einen guten Einblick in das prinzipielle Vorgehen bei einem Login gewinnen kann.
Ich wünsche viel Spaß und Erfolg beim Basteln 
Solltet Ihr Fragen zu dem Tutorial haben, so schreibt bitte einen Beitrag im Forum für Allgemeine PHP-Programmierung mit einem Verweis auf dieses Tutorial.
Danke.
Lesezeichen