PHP und CGI/fastCGI – Probleme bei HTTP-Authentifizierung beheben (PHP_AUTH_USER, PHP_AUTH_PW fehlt!)

Ich habe in den letzten zwei Tagen bei einem Kunden ein Projekt installiert, das auf PHP 5.3 basiert und bisher auf keinem einzigen Server Probleme gemacht hat. Auf dem Server (Strato Managed Server) des Kunden funktionierte jedoch leider der Login in den Adminbereich nicht mehr. Nach kurzer Ursachenforschung stellte sich schnell heraus, dass die beiden Variablen $_SERVER[„PHP_AUTH_USER“] und $_SERVER[„PHP_AUTH_PW“]  überhaupt nicht vorhanden waren.

In der Folge versendete mein Skript nun ständig neue Login-Aufforderungen, die natürlich auch bei korrekter Eingabe als falsch zurückgewiesen wurden. Mein Code zum Erzeugen des Login-Fensters sieht im Übrigen so aus:

$auth = $this->request->getAuthData();
    if(isset($auth["user"]) && $auth["user"] == "ADMIN" && $auth["pass"] == "GEHEIM")
    {
      $this->session->is_admin = true;
    }
    else
    {
      $this->response->addHeader("WWW-Authenticate", "Basic realm=\"PROJEKT\"");
      $this->response->setStatus("401 Unauthorized");
      $this->response->send();
      $this->session->is_admin  = false;
      die("Login verweigert");
    }

Es wird solange der WWW-Authenticate: Basic realm=“…“ – Header und der Status „401 Unauthorized“ gesendet, bis der Besucher die richtigen Benutzerdaten eingegeben hat oder genervt abbricht. Da $auth[„user“] und $auth[„pass“] nicht vorhanden sind, klapppt der Login nie. Die $auth-Variable ist im Grunde nur der für die Authentifizierung notwendige Teil des $_SERVER-Arrays, der von meinem Framework vorher ausgelesen und validiert wurde, was aber aufgrund des in diesem Artikel beschriebenen Problems nicht geht.

Die Lösung des Problems ist relativ simpel, wenn man mod_rewrite auf dem Server zur Verfügung hat. Ich zeige Euch nun, wie es geht.

Zuerst muss man wissen, dass das Problem darin liegt, dass der HTTP-Server (meist Apache) die Authentifizierungsdaten zwar bekommt, diese aber nicht an PHP weitergibt, da dies im CGI-Modus bzw. fastCGI-Modus ein eigener Prozess ist und kein Modul des HTTP-Servers. mod_rewrite ist jedoch ein solches Modul und kann uns hier weiterhelfen.

Zuerst öffnen wir also die .htaccess im entsprechenden Projektverzeichnis bzw. erstellen diese, falls sie noch nicht existiert. Die folgende Zeile muss jetzt sinnvoll eingebunden werden.

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Mit sinnvoll meine ich, dass sie an einer Stelle in der RewriteRule-Kette angebracht werden muss, in der sie auf jeden Fall erreicht wird. In meinem Beispiel sieht das dann so aus.

Options -MultiViews

RewriteEngine On

#Die folgende Zeile ist wichtig
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?query=$1 [QSA,L]

Die RewriteRule aus dem ersten Codebeispiel steht bei mir an erster Stelle, da sie dann auf jeden Fall ausgeführt wird. Im Netz habe ich eine andere Variante mit dem L-Modifier gefunden. Dieser bewirkt, dass danach keine weiteren Rules mehr beachtet werden (L = „last“). Das halte ich in den meisten Fällen für unklug, außer man benutzt selbst keine Rewrite-URLs.

Soweit, so gut. Das war der erste Schritt in Richtung funktionierender HTTP-Authentifikation. Um die Daten jetzt sinnvoll und bequem nutzen zu können, muss die index.php bzw. eine andere zentrale Stelle im Projekt um folgenden Code erweitert werden. Am besten ist es, wenn der irgendwo am Skript-Anfang steht, wo er auf jeden Fall immer ausgeführt wird.

if(preg_match('/Basic+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches))
{
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
}

In $_SERVER[„HTTP_AUTHORIZATION“] steht im Falle einer Authentifierung über das HTTP etwas wie  „Basic+username:password“. Allerdings sind Username und Passwort base64-codiert, weshalb wir erstmal dekodieren müssen,  um danach mittels explode() den Benutzernamen vom Passwort trennen zu können. Anschließend wird das entstandene 2-elementige Array den Variablen $_SERVER[„PHP_AUTH_USER“] und $_SERVER[„PHP_AUTH_PW“] mithilfe von list() zugewiesen.

Und ihr merkt schon, was jetzt passiert ist. Die Daten können weiterhin exakt so wie immer verwendet werden. Im restlichen Skript muss nichts mehr geändert werden, da dort sowieso nur mit $_SERVER[„PHP_AUTH_USER“] und $_SERVER[„PHP_AUTH_PW“] gearbeitet wird. Damit dürften die Probleme dann der Vergangenheit angehören, zumindest bei mir 😉

Englische Seiten, die das selbe Thema behandeln, findet ihr hier und hier.

Ich hoffe, ich konnte Euch dabei helfen, das Problem zu verstehen und zu beheben. Solltet Ihr noch fragen haben, könnt Ihr diese gerne im Kommentarbereich posten!

1 Star2 Stars3 Stars4 Stars5 Stars (1 Stimme, durchschnittlich 5,00 / 5)
Loading...


Ein Kommentar zu “PHP und CGI/fastCGI – Probleme bei HTTP-Authentifizierung beheben (PHP_AUTH_USER, PHP_AUTH_PW fehlt!)”

  1. Sehr hilfreicher Beitrag, wir haben auch etwas in dem ähnlichen Bereich geschrieben, villeicht wird es euch interessieren. Unseren Artikel über Cake PHP finden sie auf:
    https://oxidian.ch/cakephp/

Hinterlasse einen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

»Informationen zum Artikel

Autor: Simon
Datum: 25.01.2012
Zeit: 12:03 Uhr
Kategorien: Fehlermeldungen, Codeschnipsel, Wissenswertes
Gelesen: 11535x heute: 5x

Kommentare: RSS 2.0.
Diesen Artikel kommentieren oder einen Trackback senden.

»Meta