# Administrationsbereich

Durch Fehler wird man klug! In manchen Verwaltungen sind offensichtlich nie Fehler gemacht worden.
Willy Meurer (* 1934), dt.-kanadischer Publizist

So dramatisch uns der Verwaltungsapparat in Deutschland auch die Stimmung vermiesen kann, genauso wichtig ist er. Ohne Verwaltung wäre Chaos vorprogrammiert, und damit das CMS nicht darunter leiden muss, soll es noch einen Bereich erhalten, wo News, Artikel, Downloads und Links bequem verwaltet werden können.

# Verzeichnisse und Dateien

Der Adminbereich wurde in ein eigenes Verzeichnis gelegt, um eine saubere Trennung vom Userfrontend zu ermöglichen. Insgesamt befinden sich in dem Verzeichnis 15 Dateien.

  • index.php
    Dies ist die Hauptdatei der Administrationsoberfläche und stellt die Basis dar.
  • login.php und logout.php
    Diese beiden Dateien dienen dem An- und Abmelden. Sie initialisieren die Session und prüfen den Benutzernamen sowie das Kennwort bzw. löschen die Session bei der Abmeldung.
  • article*.php
    Diese drei Dateien dienen zum Löschen, Einfügen und Aktualisieren von Artikeln.
  • download*.php
    Diese drei Dateien dienen zum Löschen, Hinzufügen und Aktualisieren von Downloads.
  • link*.php
    Diese drei Dateien dienen zum Löschen, Hinzufügen und Aktualisieren von Links.
  • news*.php
    Diese drei Dateien dienen zum Löschen, Einfügen und Aktualisieren von News.

Die Datei index.php im admin-Verzeichnis entspricht vom Aufbau und der Funktionsweise her der Datei index.php aus dem Hauptverzeichnis. Es gibt nur ein paar kleinere Unterschiede:

  1. Anstelle der functions.inc.php wird die adminfunction.inc.php eingebunden, die die Funktionen für den Adminbereich enthält.
  2. Zusätzlich wird die Datei login.inc.php eingebunden, die Funktionen für die Authentifizierung des Benutzers enthält.
  3. Fast alle Anweisungen in der Datei index.php sind in einem if-Anweisungsblock notiert. Nur, wenn das Ergebnis der Funktion is_logged_in wahr ist, werden die Anweisungen ausgeführt.

# Anmelden im Adminbereich

Wie zuvor erwähnt wurde, erzeugt die Datei index.php nur dann eine Ausgabe, wenn das Ergebnis der Funktion is_logged_in gleich true ist. Diese Funktion wurde in der login.inc.php definiert.

<?php

	/* Session initialisieren */
	session_start();
	
	/* �berpr�ft, ob ein Login erfolgt ist */
	function is_logged_in()
	{
		global $base;
		
		/* User angemeldet? */
		if($_SESSION['authenticated'] == true)
		{
		  return true;
		}
		/* Login ausgeben */
		else
		{
			$content = '<h4>Login</h4>';
			$content .= '<form action="login.php" method="post">';
			$content .= '<table border="0" cellpadding="2" cellspacing="0">';
			$content .= '<tr>';
			$content .= '<td>Benutzername:</td><td><input type="text" name="username" size="32" maxlength="64"></td>';
			$content .= '</tr><tr>';
			$content .= '<td>Passwort:</td><td><input type="password" name="password" size="32"></td>';
			$content .= '</tr><tr>';
			$content .= '<td></td><td><input type="submit" value="Login"></td>';
			$content .= '</tr>';
			$content .= '</table>';
			$content .= '</form>';
			
			$template = get_file_as_string($base['adm_template']);
			$template = str_replace($base['tag_start'].'title'.$base['tag_end'],$base['adm_title'],$template);
			$template = str_replace($base['tag_start'].'shortnav'.$base['tag_end'],'&nbsp;',$template);
			$template = str_replace($base['tag_start'].'navigation'.$base['tag_end'],'&nbsp;',$template);
			$template = str_replace($base['tag_start'].'content'.$base['tag_end'],$content,$template);
			$template = str_replace('$PHP_SELF',$PHP_SELF,$template);
			echo stripslashes($template);
		  return false;
		}
	}

?>

Listing 5.1: Die Datei login.inc.php

Da beim Einbinden einer Datei alle Anweisungen, die darin notiert sind, ausgeführt werden, erfolgt zunächst die Initialisierung der Session mittels

session_start();

Anschließend erfolgt die Definition der Funktion is_logged_id. Diese Funktion stellt im ersten Schritt das Konfigurationsarray $base mittels global innerhalb der Funktion zur Verfügung.

global $base;

Daraufhin wird überprüft, ob im superglobalen $_SESSION-Array das Element authenticated existiert und dessen Wert gleich true ist. Existiert das Element nicht oder ist der Wert ungleich true, ergibt diese Überpüfung false und der else-Anweisungsblock wird ausgeführt. Für den Fall, dass das Ergebnis wahr ist, liefert die Funktion true zurück. Dies bedeutet, dass der Benutzer sich bereits erfolgreich angemeldet hat.

Wenn das Ergebnis der Prüfung false ist, muss dem Benutzer die Möglichkeit geboten werden, sich am System anzumelden. Dazu wird im else-Zweig ein Formular festgelegt, das dem Benutzer die Eingabe eines Benutzernamens und eines Passworts erlaubt. Diese wird auf Grundlage des verwendeten Templates im Browser ausgegeben.

Als Ziel für die Formulardaten wurde das Script login.php festgelegt.

Login-Screen des Adminbereichs
Abbildung 5.1: Login-Screen des Adminbereichs

# Das Script login.php

Die Aufgabe dieses Scripts besteht darin, den Benutzernamen und das Kennwort entgegenzunehmen und in der Datenbank nachzusehen, ob es eine solche Kombination gibt. Außerdem muss der Account des entsprechenden Benutzers aktiviert sein. Es wird also eine zusätzliche Tabelle in der Datenbank benötigt, in der die Benutzeraccounts gespeichert und verwaltet werden können.

Feld Typ Optionen
id INT AUTO_INCREMENT PRIMARY KEY
username VARCHAR(64) UNIQUE
password VARCHAR(255)
email VARCHAR(255) UNIQUE
active ENUM('true','false')

Tabelle 5.1: Definition der Tabelle user

Das Attribut UNIQUE für die Felder username und email bedeutet, dass Werte in diesen Spalten eindeutig sein müssen, also keine doppelten Einträge vorkommen dürfen. Das Feld active legt fest, ob der Account freigeschaltet ist oder gesperrt wurde. Dazu wurde mit ENUM ein Quasi-Boolean erschaffen. Dieses Feld kann nur die Werte true oder false speichern.

Die SQL-Anweisung zum Erzeugen dieser Tabelle sieht folgendermaßen aus:

CREATE TABLE user (  
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  
  username VARCHAR(64) NOT NULL UNIQUE,  
  password VARCHAR(255) NOT NULL,  
  email VARCHAR(255) NOT NULL,  
  active ENUM('true','false') NOT NULL DEFAULT 'false'  
)

Damit Sie sich beim ersten Mal einloggen können, sollten Sie einen Benutzer anlegen. Dafür können Sie das PHP-Script create_admin.php im Verzeichnis install nutzen. Dieses sollten Sie anschließend löschen.

Das eigentliche Script login.php enthält folgende Anweisungen:

<?php

    /* Session initialisieren */
    session_start();
    
    /* übergebene Variablen auslesen */
    $username = $_POST['username'] ? $_POST['username'] : false;
    $password = $_POST['password'] ? $_POST['password'] : false;

    if($username && $password)
    {
        /* verschlüsseltes Passwort erzeugen */
        $encrypted = md5($username,$password);    

        include('../inc/database.inc.php');
        $connection = mysql_connect($db['host'],$db['uid'],$db['pwd']);
        if($connection)
        {
        if(mysql_select_db($db['db']))
        {
            $sql = "SELECT id FROM user WHERE (username = '$username') AND (password = '$encrypted') AND (active = 'true')";
            $result = mysql_query($sql);
            if($result && (@mysql_num_rows($result) > 0))
            {
                $row = mysql_fetch_row($result);
                $_SESSION['authenticated'] = true;
                $_SESSION['user_id'] = $row[0];
                $_SESSION['username'] = $username;
            }
            else
            {
                $_SESSION['authenticated'] = false;
            }
        }
        }
    }
    
    /* Umleitung */
    header('Location: index.php');

?>

Listing 5.2: Das Script login.php

Zuallererst wird die Session mit session_start initialisiert, damit anschließend, bei erfolgreicher Anmeldung, die entsprechenden Informationen abgelegt werden können.

Anschließend werden die mit POST übertragenen Werte ausgelesen. Falls einer der Werte nicht übergeben wurde, wird der entsprechenden Variablen der Wert false zugewiesen. Um diesen Schritt übersichtlich zu halten, wird der dreifach-konditionale Operator benutzt.

$username = $_POST['username'] ? $_POST['username'] : false;  
$password = $_POST['password'] ? $_POST['password'] : false;

Nur wenn die Werte der Variablen $username und $password beide ungleich false sind, wird der Prozess zum Authentifizieren des Benutzers gestartet.

Dazu muss erst einmal das in der Datenbank verschlüsselte Passwort erzeugt werden. Dazu wird der Funktion md5 der Benutzername als »Suppe« und das Passwort als »Salz« übergeben und das Ergebnis der Berechnung in der Variablen $encrypted gespeichert.

$encrypted = md5($username,$password);  

Im nächsten Schritt wird dann eine Verbindung zu MySQL aufgebaut, die korrekte Datenbank ausgewählt und folgende SQL-Anweisung ausgeführt:

$sql = "SELECT id FROM user WHERE (username = '$username') AND (password = '$encrypted') AND (active = 'true')";

Diese besagt, dass das Feld id des Datensatzes der Tabelle user ausgelesen werden soll, dessen Wert in der Spalte username dem eingegebenen Benutzernamen entspricht. Außerdem muss der gespeicherte Wert in password dem Wert von $encrypted entsprechen und das Feld active = true sein.

Wurde eine Ergebniskennung zurückgegeben und ist die Anzahl der Datensätze in der Ergebnistabelle größer als 0, dann wurde ein passender Datensatz gefunden und die Eingaben des Benutzers waren korrekt.

if($result && (@mysql_num_rows($result) > 0))

Der Datensatz kann aus der Tabelle ausgelesen werden, und die entsprechenden Werte können in der Session gespeichert werden. Dies bedeutet, dass authenticated auf true gesetzt wird sowie der Benutzername und die Benutzer-ID in der Session registriert werden.

$row = mysql_fetch_row($result);  
$_SESSION['authenticated'] = true;  
$_SESSION['user_id'] = $row[0];  
$_SESSION['username'] = $username;

Wurde kein Datensatz gefunden, wird $_SESSION['authenticated'] explizit auf false gesetzt.

Am Ende des Scripts erfolgt mit der Funktion header eine Umleitung zum Script index.php. Bei erfolgreicher Anmeldung wird nun die Oberfläche des Administrationsbereichs dargestellt oder aber der bereits bekannte Anmeldebildschirm.

# Abmelden

Sobald der Benutzer sich aus dem Adminbereich abmelden möchte, kommt das Script logout.php zum Tragen. Dessen Aufgabe beschränkt sich einzig und allein auf das Löschen der Session.

<?php

	/* Session initialisieren */
	session_start();
	
	/* Wert setzen */
	$_SESSION['authenticated'] = false;
	$_SESSION['username'] = '';
	$_SESSION['user_id'] = '';
	
	/* Session beenden */
	session_destroy();
	
	/* Umleitung */
	header('Location: index.php');

?>

Listing 5.3: Das Script logout.php

Sicherheitshalber werden die in der Session gespeicherten Werte so verändert, dass ein anderer Benutzer des Computers nicht aus Versehen den Adminbereich trotz Abmeldung nutzen kann. Anschließend wird mit session_destroy die Sitzung beendet und wieder auf die index.php umgeleitet, die nun einen Anmeldebildschirm präsentieren wird.

# Anmerkungen

Der Rest des Adminbereichs unterscheidet sich nur geringfügig vom Quellcode des CMS. Die Scripts im admin-Verzeichnis, die im Namen insert, update oder del tragen, dienen lediglich dazu, die Formulardaten entgegenzunehmen und die entsprechenden SQL-Anweisungen auszuführen. Dabei wird auch hier darauf geachtet, dass der Benutzer eingeloggt ist, bevor die Daten permanent in der Datenbank gespeichert werden.