Kapp-Hamburg
Web-Entwicklung & Hosting – Thorben Nissen

Apache + mod_rewrite: Einzelne Verzeichnisse von "Basic Authentication" ausschließen

Manchmal möchte man eine Website bzw. -anwendung per Basic Authentication schützen, aber bestimmte Verzeichnisse öffentlich erreichbar lassen. Es finden sich dazu viele Beispiele, bei denen entweder die <Location>-Direktive verwendet oder ohne mod_rewrite gearbeitet wird. In einer modernen Webanwendung ist mod_rewrite allerdings nicht mehr wegzudenken. Des Weiteren kann es manchmal nötig sein, den Passwortschutz in der .htaccess-Datei unterzubringen, womit die Verwendung der <Location>-Direktive nicht möglich ist.

Die Besonderheit von Basic Authentication in Verbindung mit mod_rewrite ist, dass der Apache die Regeln für die Basic-Authentication zwei mal anwendet. Nämlich zuerst für den primären Request, der u.a. auch die vom Client angefragte URL in der Variable REQUEST_URI enthält und danach den internen Subrequest, nach dem Rewrite-Regeln angewandt wurden. Leitet man z.B. alle Anfragen, die nicht auf eine Datei, einen Link oder ein Verzeichnis passen auf die index.php um, so enthält im Subrequest die Variable REQUEST_URI den Wert /index.php. Das führte in unserem Fall dazu, dass die Freigabe eines bestimmten Verzeichnisses im ersten Request zwar zulässig war, im zweiten, internen aber nicht mehr. Gelöst haben wir das folgender Maßen: 

# Aktivieren der Rewrite engine
RewriteEngine On
# Setzen einer Umgebungsvariable per RewriteRule für die gewünschten URLs
# Hierbei darauf achten, dass die URLs keinen "/" am Anfang haben.
# Auf keinen Fall das Flag L für Last setzen, damit die weiteren Rewrites ausgeführt werden
RewriteRule ^the-url/you-want/to-match/.*$ - [E=MATCH_DOWNLOAD_URL:1]
# Die normalen Rewrites für unsere Anwendung
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php [NC,L]
# Basic authentication aktivieren
AuthType Basic
AuthName "Please login"
AuthUserFile /absolute/path/to/.htpasswd
# Zugriff auf die gewünschte URL erlauben (trifft den primären Request)
Require expr %{REQUEST_URI} =~ m#^/the-url/you-want/to-match/.*$#
# Zugriff erlauben, wenn die Umgebungsvariable gesetzt ist (trifft den Subrequest)
Require env REDIRECT_MATCH_DOWNLOAD_URL
# Ansonsten nach Benutzername und Passwort fragen
Require valid-user

Die einzelnen Require-Direktiven verhalten sich standardmäßig wie im <RequireAny>, d.h. eine erfüllte Bedingung reicht aus, um den Request als authentifiziert anzusehen.