Sichere Downloads mit X-Accel-Redirect

Um den Zugriff auf bestimmte Dateien in Ihrem Webspace mithilfe einer PHP oder Python Applikation zu steuern können Sie X-Accel-Redirect (auch als X-SendFile bekannt) verwenden.

Wir empfehlen diese Vorgehensweise besonders bei komplexeren Zugriffssteuerungen (ACLs, ...), aber auch bei einfachen Fällen als "schicke" Alternative zur reinen HTTP Authentifizierung. Sie haben mit der hier dokumentierten Methode die volle Flexibilität Ihrer Applikation um den Zugriff zu steuern und können z.B. mit Sessions arbeiten.

Beispiel

Sie haben eine Website unter http://www.meinedomain.de/ und wollen eine bestimmte Datei, z.B. "geheim.pdf", nur nach einer Authentifizierung durch ein Passwort oder bestimmtes Cookie etc. ausliefern.

Sie haben unter anderem folgende Einstellungen für die Domain www.meinedomain.de vorgenommen:

HTTP
Dokumenten Wurzelverzeichnis: /srv/http/web1234/www.meinedomain.de/htdocs
WSGI/PHP
URI "/" zeigt auf "WSGI Applikation"

Legen Sie nun ein sicheres Verzeichnis außerhalb Ihres Dokumenten Wurzelverzeichnisses an, z.B.: /srv/http/web1234/www.meinedomain.de/protected

In dieses Verzeichnis laden Sie die Datei "geheim.pdf". Der vollständige Pfad zu dieser Datei ist folglich: /srv/http/web1234/www.meinedomain.de/protected/geheim.pdf

Anschließend müssen Sie dieses sichere Verzeichnis in der Domain-Konfiguration eintragen:

Statisch
URI "/protected/" zeigt auf Pfad
"/srv/http/web1234/www.meinedomain.de/protected/",
desweiteren ist das Häkchen bei "Erlaube nur interne Anfragen" gesetzt.

Dieser statische URI Pfad ist von aussen nicht erreichbar, kann aber intern von Ihrer Applikation per X-Accel-Redirect referenziert werden. Sie können den Webservern somit dynamisch das Kommando geben eine bestimmte Datei auszuliefern.

Stellen Sie sich nun also einen Besucher auf http://www.meinedomain.de/ vor. Ihre Applikation liefert einen Login-Bildschirm aus. Der Besucher meldet sich erfolgreich an und befindet sich nun auf http://www.meinedomain.de/intern/. Hier erzeugt Ihre Applikation einige Links, unter anderem einen Link auf die geschützte Datei "geheim.pdf".

Die URL können Sie frei bestimmen, sie darf nur nicht unterhalb von "/protected/" liegen. Nehmen wir als Beispiel die URL http://www.meinedomain.de/download/geheim.pdf an. Der Besucher klickt auf den Link und Ihre Applikation erhält einen üblichen GET-Request für "/download/geheim.pdf".

An dieser Stelle können Sie eine Zugriffskontrolle einbauen, die z.B. prüft, ob der angemeldete Benutzer ausreichende Rechte hat um die Datei herunter zu laden.

Nehmen wir nun an Sie erlauben dem Benutzer die Datei herunter zu laden. Anstatt die Datei mit Ihrer Applikation einzulesen und ineffizient zum Webserver und letztendlich zum Besucher durchzureichen können Sie folgendes tun:

Liefern Sie eine leere HTTP Antwort (HTTP Status-Code: 200) mit den entsprechenden Headern aus:

Beispiel mit PHP

header("Content-Type: application/pdf");
header("X-Accel-Redirect: /protected/geheim.pdf");

Beispiel mit Python (Flask)

response = Flask.make_response()
response.headers['Content-Type'] = 'application/pdf'
response.headers['X-Accel-Redirect'] = '/protected/geheim.pdf'

Achtung!

X-Accel-Redirect erwartet eine absolute URI mit "/" am Anfang!

Die Webserver fangen diese HTTP Antwort von den Appservern ab und liefern nun die Datei /srv/http/web1234/www.meinedomain.de/protected/geheim.pdf mit dem entsprechenden Content-Type aus.

Diese Vorgehensweise spart unter Umständen viel Speicher und ist auf jedenfall deutlich effizienter als diverse "sendfile" Alternativen!