Zugriff auf HTTP-Authorization in PHP
Dieser Tipp beschreibt ein paar Methoden die HTTP-Authorization in PHP durchzuführen.
Es geht dabei aber nicht um eine vollständige und sichere Implementierung, sondern nur um die verschiedenen Techniken zum Zugriff.
HTTP-Authorization hat aber einen enormen Vorteil:
Es ist die einzige(1) Methode im Web ein Passwort sicher zu übertragen.
Das gilt allerdings nur für die
Auch im SSL-Tunnel sind die Passwörter selbst genauso unverschlüsselt und mit dem Aufkommen von HTTPS-Inspection in Firmen(2) damit genauso anfällig wie reguläres HTTP.
HTTPS ist nur dann als sicher zu bezeichnen, wenn man seinen kompletten Zertifikat-Store löscht und jedes Zertifikat einzeln per Fingerprint hinzufügt!
Die simpelste Methode ist es tatsächlich die
Über das
Der angemeldete Benutzer steht dann in PHP zur Verfügung:
Wenn PHP auch als Apache-Modul läuft gibt es dabei auch noch die zusätzlichen, unten erwähnten Felder, so lange der Safe-Mode nicht aktiv ist.
In der Praxis sehe ich das nicht als Option, da ein Login-Feld ja erst erscheinen soll, wenn man wirklich auf "Login" klickt.
Mit
Darum werde ich hier auch auf die anderen Apache-Module (z.B. für LDAP) nicht weiter eingehen.
Dazu muss man nur den Browser zuerst dazu bringen die Autorisierung einzufordern:
PHP verarbeitet dann die Antwort-Daten des Clients und leitet diese im nächsten Durchlauf an das Script weiter:
Das Parsen des Strings ist dem Programmierer selbst überlassen.
Ein genaueres Beispiel (und das Beispiel für
Das Problem dieser Methode ist, dass man sich hiermit auf genau eine Konfiguration einschränkt, aber PHP grade im Shared-Hosting oftmals als (F)CGI läuft, und dieser Trick nicht funktioniert, deshalb würde ich davon eher Abstand nehmen.
Der Kommentar zu dieser Methode ist der selbe wie oben
FCGI dazu bewegen den Header weiterzugeben.
Der Rest verhält sich dann wie oben.
Siehe: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiConfig
Wenn man allerdings
(Unter älteren Versionen heißt die Direktive noch
Siehe: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidpassheader
Diese Methode ist somit eigentlich nur ein Workaround für Apache-Server.
Dieser Ausdruck trifft auf jede URL zu (
In PHP selbst kann man dann die selbe Variable wie oben benutzen, um auf die Daten zugreifen zu können, wobei einige Apache-Versionen noch ein
Ob man das als eine saubere Lösung betrachtet, möchte ich mal jedem selbst überlassen
Man kann Apache aber auch dazu bringen diesen Header weiterzugeben, indem man die Compiler-Flag
Diese Methode ist (aus der Natur der Sache) natürlich nur für Leute mit eigenem (v)Server möglich, die sich ihren Apache selbst kompilieren.
Wenn man diese Methode benutzen will, bleibt also nur das Arbeiten mit Weichen oder eine strikt definierte Umgebung.
1: Javascript bietet auch die Möglichkeit ein Passwort vor dem Übertragen zu hashen, aber da es nicht zwangsweise aktiviert ist, lasse ich es hier mal unter den Tisch fallen
2: Nur zur Erinnerung: Jeder Windows- und Mac-Rechner traut standardmäßig der "Deutschen Telekom Root CA" und Firefox traut gerne Zertifikaten, die niemandem gehören wollen.
Es geht dabei aber nicht um eine vollständige und sichere Implementierung, sondern nur um die verschiedenen Techniken zum Zugriff.
Inhaltsverzeichnis
Warum?
Die HTTP-Authorization ist den meisten Benutzern und Programmieren durchhtaccess
/htpasswd
-Dateien und die wenig schönen Dialoge bekannt, weshalb sich jeder Programmierer erstmal gleich ein HTML-Formular dafür baut.HTTP-Authorization hat aber einen enormen Vorteil:
Es ist die einzige(1) Methode im Web ein Passwort sicher zu übertragen.
Das gilt allerdings nur für die
Digest
-Methode (und auf keinen Fall für die Basic
-Methode), die von jedem modernen Browser (dazu gehört der Internet Explorer 6 nicht!) unterstützt wird.Was ist mit SSL?
HTTPS wird gerne als Lösung für das Problem der unsicheren Übertragung von Passwörtern angeführt, ist es aber nicht!Auch im SSL-Tunnel sind die Passwörter selbst genauso unverschlüsselt und mit dem Aufkommen von HTTPS-Inspection in Firmen(2) damit genauso anfällig wie reguläres HTTP.
HTTPS ist nur dann als sicher zu bezeichnen, wenn man seinen kompletten Zertifikat-Store löscht und jedes Zertifikat einzeln per Fingerprint hinzufügt!
Ansätze
Im folgenden gibt es ein paar Ansätze, wie man HTTP-Authorization verwenden kann und meine zwei Cent dazu, was ich davon haltehtpasswd
-Dateien
Die simpelste Methode ist es tatsächlich die .htusers
-Dateien von Apache zu verwenden.Über das
htdigest
-CLI-Programm und einen entsprechenden Aufruf in PHP liese sich die Verwaltung der Benutzer steuern.Der angemeldete Benutzer steht dann in PHP zur Verfügung:
echo $_SERVER['REMOTE_USER']; #=> "hans"
echo $_SERVER['AUTH_TYPE']; #=> "Digest"
In der Praxis sehe ich das nicht als Option, da ein Login-Feld ja erst erscheinen soll, wenn man wirklich auf "Login" klickt.
Mit
htaccess
-Dateien müsste dies aber schon vor dem ersten Aufruf der Seite geschehen (was somit auch Google ausschließt) oder die URLs für angemeldete Benutzer müssten abweichend definiert sein.Darum werde ich hier auch auf die anderen Apache-Module (z.B. für LDAP) nicht weiter eingehen.
PHP als Apache-Modul
Wenn PHP als Apache-Modul läuft, ist es auch sehr einfach die Anmeldung zu behandeln.Dazu muss man nur den Browser zuerst dazu bringen die Autorisierung einzufordern:
$realm = "Meine Seite";
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="' . $realm .'",qop="auth",nonce="' . uniqid() . '",opaque="' . md5($realm) .'"');
echo $_SERVER['PHP_AUTH_USER']; #=> "hans"
echo $_SERVER['PHP_AUTH_DIGEST']; #=> username="hans", realm="Meine Seite", nonce="...", uri="...", response="...", opaque="...", cnonce="...", nc=00000001, qop="auth"
Ein genaueres Beispiel (und das Beispiel für
Basic
) findet sich unter http://php.net/manual/en/features.http-auth.phpDas Problem dieser Methode ist, dass man sich hiermit auf genau eine Konfiguration einschränkt, aber PHP grade im Shared-Hosting oftmals als (F)CGI läuft, und dieser Trick nicht funktioniert, deshalb würde ich davon eher Abstand nehmen.
apache_request_headers()
Eine andere Methode - wenn PHP als Apache-Modul läuft - ist dieapache_request_headers()
-Funktion, die alle Header als assoziatives Array zurückliefert.$header = apache_request_headers();
echo $header['Authorization']; #=> ...
PHP mit FastCGI
Läuft PHP übermod_fastcgi
lässt sich über die Apache-Konfigurations-OptionFastCgiConfig -pass-header Authorization
echo $_SERVER['Authorization']; #=> ...
Siehe: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiConfig
Wenn man allerdings
mod_fcgid
benutzt, lautet der EintragFcgidPassHeader Authorization
PassHeader
) und die PHP-Variable heißt wieder HTTP_AUTHORIZATION
.Siehe: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidpassheader
Diese Methode ist somit eigentlich nur ein Workaround für Apache-Server.
mod_rewrite
Der Kreativität geschuldet ist die folgende Variante (von der man auch einige Abwandlungen findet), die Apachesmod_rewrite
benutzt um den Authorization
Antwort-Header an das PHP-Skript weiterzugeben:RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
.*
), ohne sie zu verändern (-
) und hängt den zusätzlichen Wert an. Außerdem ist das die letzte Rewrite-Regel, die ausgeführt wird (L
).In PHP selbst kann man dann die selbe Variable wie oben benutzen, um auf die Daten zugreifen zu können, wobei einige Apache-Versionen noch ein
REDIRECT_
vor die Variable hängen.Ob man das als eine saubere Lösung betrachtet, möchte ich mal jedem selbst überlassen
Apache und der Authorization-Header
Das eigentliche Problem aller obigen Techniken ist, dass Apache sich weigert denAuthorization
-Header an CGI-Skripte weiterzugeben. Die Begründung dabei ist:- CGI-Skripts könnten Zugriff auf Anmelde-Informationen erhalten (was ja hier genau beabsichtigt ist)
- Ein lokaler Systembenutzer könnte mit
ps e <PID>
die Benutzerdaten auslesen (was wir auf einem Server in Kauf nehmen können, da nur root dieses Recht besitzt)
Man kann Apache aber auch dazu bringen diesen Header weiterzugeben, indem man die Compiler-Flag
-DSECURITY_HOLE_PASS_AUTHORIZATION
setzt.export CFLAGS="-DSECURITY_HOLE_PASS_AUTHORIZATION $CFLAGS"
./configure [...]
make
Diese Methode ist (aus der Natur der Sache) natürlich nur für Leute mit eigenem (v)Server möglich, die sich ihren Apache selbst kompilieren.
Fazit
Wer in einem PHP-Skript HTTP-Authorization benutzen will und dabei möglichst viele PHP- und Server-Kombinationen unterstützen will hat schlicht Pech gehabt: Es gibt keine Lösung, die auf jedem Server funktioniert, dafür allein schon 4 nur für Apache.Wenn man diese Methode benutzen will, bleibt also nur das Arbeiten mit Weichen oder eine strikt definierte Umgebung.
1: Javascript bietet auch die Möglichkeit ein Passwort vor dem Übertragen zu hashen, aber da es nicht zwangsweise aktiviert ist, lasse ich es hier mal unter den Tisch fallen
2: Nur zur Erinnerung: Jeder Windows- und Mac-Rechner traut standardmäßig der "Deutschen Telekom Root CA" und Firefox traut gerne Zertifikaten, die niemandem gehören wollen.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 155065
Url: https://administrator.de/contentid/155065
Ausgedruckt am: 21.11.2024 um 18:11 Uhr