it-swarm.com.de

PHP/Apache verwenden, um den Zugriff auf statische Dateien (html, css, img usw.) zu beschränken

Nehmen wir an, Sie haben viele HTML-, CSS-, JS-, IMG- und etc-Dateien in einem Verzeichnis auf Ihrem Server. Normalerweise kann jeder Benutzer im Internet-Land auf diese Dateien zugreifen, indem er einfach die vollständige URL wie folgt eingibt: http://example.com/static-files/sub/index.html

Was passiert, wenn Sie nur autorisierte Benutzer diese Dateien laden möchten? Nehmen wir für dieses Beispiel an, dass sich Ihre Benutzer zuerst über eine URL wie die folgende anmelden: http://example.com/login.php

Wie würden Sie dem angemeldeten Benutzer erlauben, die index.html-Datei (oder eine der Dateien unter "static-files") anzuzeigen, die Datei jedoch auf alle anderen Benutzer beschränken?

Ich habe bisher zwei mögliche Lösungen gefunden:

Lösung 1
Erstellen Sie die folgende .htaccess-Datei unter "statische Dateien":

Options +FollowSymLinks  
RewriteEngine on  
RewriteRule ^(.*)$ ../authorize.php?file=$1 [NC]

Und dann in authorize.php ...

if (isLoggedInUser()) readfile('static-files/'.$_REQUEST['file']);
else echo 'denied';

Diese authorize.php-Datei ist stark vereinfacht, aber Sie bekommen die Idee.

Lösung 2
Erstellen Sie die folgende .htaccess-Datei unter "statische Dateien":

Order Deny,Allow
Deny from all
Allow from 000.000.000.000

Und dann könnte meine Anmeldeseite diese .htaccess-Datei mit einer IP-Adresse für jeden angemeldeten Benutzer anfügen. Natürlich müsste dies auch über eine Bereinigungsroutine verfügen, um alte oder nicht mehr verwendete IP-Adressen zu löschen.


Ich mache mir Sorgen, dass meine erste Lösung auf dem Server ziemlich teuer werden könnte, da die Anzahl der Benutzer und Dateien, auf die sie zugreifen, steigt. Ich denke, meine zweite Lösung wäre viel billiger, aber auch weniger sicher aufgrund von IP-Spoofing und so weiter. Ich befürchte außerdem, dass das Schreiben dieser IP-Adressen in die htaccess-Datei zu einem Engpass der Anwendung werden könnte, wenn viele Benutzer gleichzeitig arbeiten. 

Welche dieser Lösungen klingt besser und warum? Können Sie sich alternativ eine völlig andere Lösung vorstellen, die besser ist als beide?

38
Bart

Ich würde in Betracht ziehen, einen PHP -Loader für die Authentifizierung zu verwenden und dann die benötigten Dateien zurückzugeben. Zum Beispiel anstatt <img src='picture.jpg' /> etwas wie <img src='load_image.php?image=picture.jpg' /> zu tun.

Ihr Image Loader kann Sitzungen überprüfen, Anmeldeinformationen überprüfen usw. und dann entscheiden, ob die angeforderte Datei an den Browser zurückgegeben werden soll oder nicht. Auf diese Weise können Sie alle Ihre sicheren Dateien außerhalb des über das Web zugänglichen Root-Verzeichnisses speichern, sodass niemand sie einfach "WGET" oder "versehentlich" dort durchsuchen kann.

Denken Sie daran, die richtigen Header in PHP zurückzugeben und tun Sie in php etwas wie readfile (), und der Inhalt der Datei wird an den Browser zurückgegeben. 

Ich habe dieses Setup auf mehreren großen sicheren Websites verwendet und funktioniert wie ein Zauber.

Edit: Das System, das ich gerade baue, verwendet diese Methode, um Javascript, Bilder und Video zu laden, aber CSS ist nicht sehr besorgt über die Sicherung.

34
Shane

X-Sendedatei

Es gibt ein Modul für Apache (und andere HTTP-Server), mit dem Sie dem HTTP-Server mitteilen können, dass er die von Ihnen angegebene Datei in einem Header in Ihrem PHP-Code bereitstellen soll: Ihr PHP-Skript sollte also so aussehen: 

// 1) Check access rights code
// 2) If OK, tell Apache to serve the file
header("X-Sendfile: $filename");

2 mögliche Probleme:

  1. Sie benötigen Zugriff, um Regeln neu zu schreiben (.htaccess aktiviert oder direkter Zugriff auf Konfigurationsdateien).
  2. Sie müssen das Modul mod_xsendfile zu Ihrem Apache hinzugefügt haben 

Hier ist eine gute Antwort in einem anderen Thread: https://stackoverflow.com/a/3731639/2088061

7
DenisS

Ich habe viel über das gleiche Thema nachgedacht. Ebenso unzufrieden bin ich mit der PHP Engine, die für jede kleine Ressource ausgeführt wird, die ausgeliefert wird. Ich habe vor ein paar Monaten eine Frage in der gleichen Richtung gestellt hier , allerdings mit einem anderen Fokus.

Aber ich hatte gerade eine schrecklich interessante Idee, dass funktionieren könnte .

  • Pflegen Sie irgendwo auf Ihrem Webserver ein Verzeichnis mit dem Namen /sessions.

  • Erstellen Sie bei jeder Anmeldung eines Benutzers eine leere Textdatei mit der Sitzungs-ID in /sessions. Z.B. 123456

  • Serviere Bilder in deiner PHP App wie folgt aus: /sessions/123456/images/test.jpg

  • Führen Sie in Ihrer htaccess-Datei zwei Umleitungsbefehle aus.

  • Eine, die /sessions/123456/images/test.jpg in /sessions/123456?filename=images/test.jpg übersetzt

  • Ein zweites, das alle Aufrufe von //sessions/(.*) entgegennimmt und mit dem Flag -f prüft, ob die angegebene Datei vorhanden ist. Wenn /sessions/123456 nicht vorhanden ist, bedeutet dies, dass sich der Benutzer abgemeldet hat oder seine Sitzung abgelaufen ist. In diesem Fall sendet Apache eine 403 oder leitet zu einer Fehlerseite weiter - die Ressource ist nicht mehr verfügbar.

Auf diese Weise haben wir quasi eine Sitzungsauthentifizierung in mod_rewrite, bei der nur eine "Datei existiert" -Prüfung durchgeführt wird!

Ich habe nicht genug Routine, um die mod_rewrite-Anweisungen im laufenden Betrieb zu erstellen, aber sie sollten leicht genug zu schreiben sein. (Ich schaue hoffentlich in deine Richtung @Gumbo :)

Hinweise und Vorsichtsmaßnahmen:

  • Abgelaufene Sitzungsdateien müssten mit einem Cron-Job schnell gelöscht werden, es sei denn, es ist möglich, in .htaccess nach der Uhrzeit einer Datei zu suchen (was durchaus möglich ist).

  • Das Bild/die Ressource steht jedem Client zur Verfügung , solange die Sitzung besteht, daher kein 100% iger Schutz. Sie können dies möglicherweise umgehen, indem Sie die Client-IP in die Gleichung (= den von Ihnen erstellten Dateinamen) einfügen und eine zusätzliche Prüfung für% {REMOTE_ADDR} durchführen. Dies ist eine fortgeschrittene .htaccess-Meisterschaft, aber ich bin mir ziemlich sicher, dass sie machbar ist.

  • Ressourcen-URLs sind nicht statisch und müssen bei jeder Anmeldung abgerufen werden, sodass kein Caching stattfindet.

Ich bin sehr interessiert an Rückmeldungen dazu, etwaigen Unzulänglichkeiten, die ich übersehen habe, und erfolgreichen Implementierungen (ich habe momentan nicht die Zeit, einen Test einzurichten mich selber).

5
Pekka 웃

Erstellen Sie eine Karte umschreiben , die die Anmeldeinformationen des Benutzers überprüft und diese entweder an die entsprechende Ressource oder an eine Seite mit Zugriff verweigert.

Die Aufrechterhaltung des Inhalts der htaccess-Dateien scheint ein Albtraum zu sein. Ihr erklärtes Ziel besteht auch darin, zu verhindern, dass nicht authentifizierte users nicht nicht authentifizierte client-IP-Adressen auf diesen Inhalt zugreifen.

Mehrere Benutzer scheinen von derselben IP-Adresse zu stammen

Eine einzelne Benutzersitzung scheint von mehreren Adressen zu stammen.

Ich mache mir Sorgen, dass meine erste Lösung auf dem Server als Anzahl von .__ ziemlich teuer werden könnte. Benutzer und Dateien, auf die sie zugreifen, nehmen zu

Wenn Sie verhindern möchten, dass Ihr Inhalt ausläuft und keine HTTP-Authentifizierung verwendet wird, ist der einzige Zugriff auf den Dateizugriff in einer zusätzlichen Logikebene möglich. Sie wissen auch nicht, dass die Verwendung von PHP für dieses ein Problem ist - Sie haben es getestet? Ich denke, Sie wären überrascht, wie viel Durchsatz das leisten kann, insbesondere wenn Sie einen Opcode-Cache verwenden.

Ich schätze, Ihre "Vereinfachung" des Wrappers behebt Probleme wie Mime-Typ und Caching.

C.

2
symcbean

Wenn Sie Apache verwenden, können Sie wie unten beschrieben entweder in der .htaccess- oder der httpd.conf -Datei konfigurieren. Nachfolgend ein Beispiel, um den Zugriff auf die * .inc-Datei zu verhindern. Es funktioniert sehr gut für mich. 

<Files ~ "\.inc$">
Order allow,deny
Deny from all
</Files>

Weitere Informationen finden Sie unter: http://www.ducea.com/2006/07/21/Apache-tips-tricks-deny-access-to-certain-file-types/ .

0
Hieu Phan

Angenommen, Sie möchten alle Ihre statischen Dateien schützen, und Sie müssen sie von innerhalb Ihrer Webroot-Server verwalten, Sie können alle HTTP-Methoden außer HEAD schützen. Wenn Sie autorisiert sind, senden Sie eine Kopfanforderung durch die Kopfzeilen und senden den Dateikontent als Hauptteil. Dies ist zwar teuer, aber Sie sind geschützt und haben dasselbe Verhalten.

0
Andreas Dyballa

Ich habe eine dynamische Webanwendung geschrieben und auf dem Webshere Application Server bereitgestellt. So sichern Sie meine statischen Dateien:

Ich habe zuerst hinzugefügt 

<login-config id="LoginConfig_1">
  <auth-method>FORM</auth-method>
    <realm-name>Form-Based Authentication</realm-name>
      <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/login_error.html</form-error-page>
       </form-login-config>
</login-config>

in web.xml wird Ihr Webserver angewiesen, die formularbasierte Authentifizierung zu verwenden (der Code für die Anmeldung ist unten angegeben). 

code zur Login-Seite:

<form id="form1" name="form1" method="post" action="j_security_check" style="padding: 0px 0px 0px 12px;">
        Username: 
          <label>
          <input name="j_username" type="text" class="font2" />
        </label>

        <br />
        <br />
        Password:
        <span class="font2" >
        <label>
      <input name="j_password" type="password" class="font2" />
      </label>
      </span> 
        <br />
        <br />
            <label>
        <input type="submit"  class="isc-login-button" name="Login" value="Login" />
        </label>
    </form></td>

Um eine formularbasierte Anmeldung zu ermöglichen, müssen Sie Ihren Webserver so konfigurieren, dass er eine bestimmte Benutzerregistry verwendet, die LDAP oder Datenbank sein kann.

Sie können Ihre sicheren Ressourcen deklarieren. Wenn ein Benutzer versucht, auf diesen Ressourcencontainer zuzugreifen, wird automatisch geprüft, ob der Benutzer authentifiziert ist oder nicht. Selbst Sie können Rollen auch mit den sicheren Ressourcen verknüpfen. Dazu habe ich folgenden Code in meine web.xml eingefügt

<security-constraint>
        <display-name>Authenticated</display-name>
        <web-resource-collection>
            <web-resource-name>/*</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>PUT</http-method>
            <http-method>HEAD</http-method>
            <http-method>TRACE</http-method>
            <http-method>POST</http-method>
            <http-method>DELETE</http-method>
            <http-method>OPTIONS</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>Auth Roles</description>
            <role-name>role1</role-name>            
            <role-name>role2</role-name>            
        </auth-constraint>
    </security-constraint>

    <security-role>
        <role-name>role1</role-name>
    </security-role>
    <security-role>
        <role-name>role2</role-name>
    </security-role>

Mit diesem Code kann der Benutzer keine statischen Dateien sehen (seit/*), bis er unter der Rolle "Rolle1" und "Rolle2" angemeldet ist. Auf diese Weise können Sie Ihre Ressourcen schützen.

0
GG.

Ich habe möglicherweise einen Vorschlag, der auf iframe und HTTP_REFERER basiert, aber es ist nicht kugelsicher, und es hängt davon ab, was genau Sie mit diesem Zugriff schützen möchten.

Wenn jedoch verhindert wird, dass eine vollständige statische Seite ohne Authentifizierung angezeigt wird, können Sie Folgendes tun:

1 - Verwenden Sie eine Seite PHP, um den Benutzer zu authentifizieren

2 - Weiterleitung auf eine andere PHP - Seite, die einen Schlüssel in der URL und einen Iframe enthält, der mit Ihrem statischen Inhalt im Rumpf verlinkt ist:

<iframe src="static/content.html" />

3 - Dann könnten Sie in Ihrem Zugriff den Schlüssel im HTTP_REFERER auf folgende Weise überprüfen:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !AUTH_KEY
RewriteCond %{REQUEST_URI} ^/path/to/protected/page$
RewriteRule . - [F]

4 - Schließlich, wenn Sie es dynamischer gestalten möchten und nicht jedes Mal den gleichen Schlüssel verwenden möchten, wenn Sie rewrite map verwenden können, wie von Ignacio Vazquez-Abrams vorgeschlagen, oder eine Datei mit der Benutzer-IP als Dateiname erstellen und prüfen, ob die Datei mit REMOTE_ADDR vorhanden ist Entfernen Sie die Datei nach einer Weile.

Denken Sie jedoch daran, dass das Verhalten von iframe + HTTP_REFERER von Browser-Sitzung zu Browser sowie von REMOTE_ADDR variieren kann.

0
RafaSashi