Christoph: SetEnfIf auf SESSION anwendbar?

Hallo zusammen,

mich würd interessieren, ob ich in der Apache httpd.conf Datei eine Enviroment "Variable" über das Vorhandensein einer (PHP-) Session Variable erstellen kann...
die Idee ist, dass bestimmte Ordner und Dateien nicht zugänglich sein sollen, wenn der User nicht eingeloggt ist. D. h., dass ich mir (bzw. dem user) das einloggen über .htaccess sparen möchte.

Code würde ungefähr so aussehen:

SetEnvIf $_SESSION["access"] access_granted
<Directory /topsecret>
    Order Deny,Allow
    Deny from all
    Allow from env=access_granted
</Directory>

nur eben $_SESSION["access"] scheint mir nich so einfach zu erreichen zu sein...

wär super, wenn da jemand an tip für mich hätt...

grüße
Christoph

  1. echo $begrüßung;

    mich würd interessieren, ob ich in der Apache httpd.conf Datei eine Enviroment "Variable" über das Vorhandensein einer (PHP-) Session Variable erstellen kann...

    Werte von PHPs Session-Variablen leben außerhalb von PHP meist in Dateien. Wenn es dir gelingt, die zur Session gehörige Datei zu finden, sie zu interpretieren, ...

    die Idee ist, dass bestimmte Ordner und Dateien nicht zugänglich sein sollen, wenn der User nicht eingeloggt ist. D. h., dass ich mir (bzw. dem user) das einloggen über .htaccess sparen möchte.

    Ein in PHP geschriebenes Zugriffsscript, das je nach Session-Status die (auerhalb des DocumentRoots liegenden) Dokumente ausliefert sollte deutlich einfacher zu realisieren sein.

    echo "$verabschiedung $name";

    1. echo $begrüßung;

      if (in_array($begrüßung,$freundliche_begrüßungen){
          echo 'danke soweit';}

      Werte von PHPs Session-Variablen leben außerhalb von PHP meist in Dateien. Wenn es dir gelingt, die zur Session gehörige Datei zu finden, sie zu interpretieren, ...

      jo, das wär ja au super... wenn mir jemand sagt, wie ich SetEnvIf aus ner Datei erstellen kann, würd mir des ausreichend helfen, wenn i mi a bissle anstreng, dann krieg i scho raus, wo die session variable wohnt (und wo ihr auto steht)

      die Idee ist, dass bestimmte Ordner und Dateien nicht zugänglich sein sollen, wenn der User nicht eingeloggt ist. D. h., dass ich mir (bzw. dem user) das einloggen über .htaccess sparen möchte.

      Ein in PHP geschriebenes Zugriffsscript, das je nach Session-Status die (auerhalb des DocumentRoots liegenden) Dokumente ausliefert sollte deutlich einfacher zu realisieren sein.

      naja, stimmt scho, aber da da au pdf dateien liegen, die ich über embeded einbind, is des so net ganz so leicht zu machen...

      grüße
      Christoph

      1. Hi,

        jo, das wär ja au super... wenn mir jemand sagt, wie ich SetEnvIf aus ner Datei erstellen kann, würd mir des ausreichend helfen

        Vermutlich kaum, ohne ein zusaetzliches Apache-Modul selbst zu schreiben ...

        Ein in PHP geschriebenes Zugriffsscript, das je nach Session-Status die (auerhalb des DocumentRoots liegenden) Dokumente ausliefert sollte deutlich einfacher zu realisieren sein.

        naja, stimmt scho, aber da da au pdf dateien liegen, die ich über embeded einbind, is des so net ganz so leicht zu machen...

        Auf Script verlinken; Script Authentifizierung checken, Script entsprechende Header [1] generieren lassen; PDF-Daten auslesen und hinterherschicken, fertig.

        [1] U.a. Content-Type-Header; speziell bei PDFs wollen aber auch noch einige Angaben bzgl. Caching etc. beruecksichtigt werden, da sonst diverse Browser Probleme machen.

        MfG ChrisB

        --
        "The Internet: Technological marvel of marvels - but if you don't know *what* you're lookin' for on the Internet, it is nothing but a time-sucking vortex from hell."
        1. Hallo ChrisB,

          jo, das wär ja au super... wenn mir jemand sagt, wie ich SetEnvIf aus ner Datei erstellen kann, würd mir des ausreichend helfen

          Vermutlich kaum, ohne ein zusaetzliches Apache-Modul selbst zu schreiben ...

          hoffentlich hast du da nicht recht. is eigentlich schon der Lösungsansatz, den ich gerne fahren würde, da es zum einen dem chef seine Vorgabe is und da zum anderen so einfach generell alle möglichen Dateien geschützt sind, nich nur die pdfs...

          Ein in PHP geschriebenes Zugriffsscript, das je nach Session-Status die (auerhalb des DocumentRoots liegenden) Dokumente ausliefert sollte deutlich einfacher zu realisieren sein.

          naja, stimmt scho, aber da da au pdf dateien liegen, die ich über embeded einbind, is des so net ganz so leicht zu machen...

          Auf Script verlinken; Script Authentifizierung checken, Script entsprechende Header [1] generieren lassen; PDF-Daten auslesen und hinterherschicken, fertig.

          is schon au ne Lösung, klar, nur dummerweise hab ich die pdfs im moment über embeded drin, das heißt, dass der client erst das html geschickt bekommt, und sich erst dann darum kümmert, dass das pdf geladen wird, wodurch ich nicht direkt die authentifizierung prüfen kann.

          grüße
          c.

          1. echo $begrüßung;

            Vermutlich kaum, ohne ein zusaetzliches Apache-Modul selbst zu schreiben ...
            hoffentlich hast du da nicht recht. is eigentlich schon der Lösungsansatz, den ich gerne fahren würde, da es zum einen dem chef seine Vorgabe is und da zum anderen so einfach generell alle möglichen Dateien geschützt sind, nich nur die pdfs...

            Was hindert dich daran, alle betroffenen Dokumente in ein Verzeichnis außerhalb des DocumentRoots zu legen und dann ein Script zu schreiben, das anhand eines Parameters einen Dateinamen entgegennimmt, die Zugangsberechtigung prüft, ebenfalls prüft, ob die Datei im Dokumente-Verzeichnis liegt, und dann diese Datei an den Aufrufer durchreicht? Das ist das klassische Download-Script-Konzept, erprobt und bewährt.

            Auf Script verlinken; Script Authentifizierung checken, Script entsprechende Header [1] generieren lassen; PDF-Daten auslesen und hinterherschicken, fertig.
            is schon au ne Lösung, klar, nur dummerweise hab ich die pdfs im moment über embeded drin, das heißt, dass der client erst das html geschickt bekommt, und sich erst dann darum kümmert, dass das pdf geladen wird, wodurch ich nicht direkt die authentifizierung prüfen kann.

            Jeder Request ist selbständig zu betrachten. Ob die Ursache des Requests ein Verweis aus einem anderen Dokument ist oder jemand die URL zu Fuß im Browser eingegeben hat ist vollkommen uninteressant. Jeder Request hat auch wieder erneut die Zugriffsberechtigung zu prüfen. Das kann der Webserver mit seiner eingebauten HTTP-Authentication sein oder, da du das ja nicht willst, ein PHP-Script.

            echo "$verabschiedung $name";

          2. Hi,

            Auf Script verlinken; Script Authentifizierung checken, Script entsprechende Header [1] generieren lassen; PDF-Daten auslesen und hinterherschicken, fertig.

            is schon au ne Lösung, klar, nur dummerweise hab ich die pdfs im moment über embeded drin, das heißt, dass der client erst das html geschickt bekommt, und sich erst dann darum kümmert, dass das pdf geladen wird, wodurch ich nicht direkt die authentifizierung prüfen kann.

            Natuerlich kannst du - *genau* *dafuer* benutzt man doch Sessions, um mehrere zeitlich nacheinander erfolgende Requests einem Client zuordnen zu koennen.

            Wenn der Client sich also einmal authentifiziert hat, hinterlegst du diese Info in der Session - und das die geschuetzten Daten ausliefernde Script ueberprueft diese dann erst mal.

            MfG ChrisB

            --
            "The Internet: Technological marvel of marvels - but if you don't know *what* you're lookin' for on the Internet, it is nothing but a time-sucking vortex from hell."
            1. hallo,

              is schon au ne Lösung, klar, nur dummerweise hab ich die pdfs im moment über embeded drin, das heißt, dass der client erst das html geschickt bekommt, und sich erst dann darum kümmert, dass das pdf geladen wird, wodurch ich nicht direkt die authentifizierung prüfen kann.

              Natuerlich kannst du - *genau* *dafuer* benutzt man doch Sessions, um mehrere zeitlich nacheinander erfolgende Requests einem Client zuordnen zu koennen.

              Wenn der Client sich also einmal authentifiziert hat, hinterlegst du diese Info in der Session - und das die geschuetzten Daten ausliefernde Script ueberprueft diese dann erst mal.

              die eigentliche frage ist die: ich logge mich in eine seite ein auf der dann ein bild angezeigt wird. ob mir das bild angezeigt werden soll kann das script leicht überprüfen (z. B. mit hilfe einer session). eingebunden wird das bild beispielsweise durch

              <img src="/pics/bild1.jpeg"...

              das script überprüft nur, ob der html code mit obigem image tag geschickt wird. das bild wird aber nicht direkt mitgeschickt. nach meinem verständnis erfolgen hier zwei anfragen an den server. die erste kriegt den html code geschickt (wenn die rechte da sind), bei der zweiten wird das bild geschickt.

              gebe ich nun die domain + /pics/bild1.jpeg in meinen browser ein (ohne session id, etc) dann wird im normalfall dieses bild auch angezeigt. das möchte ich vermeiden, da es nach meinem geschmack eine lücke ist.

              grüße
              c.

              1. Hallo,

                gebe ich nun die domain + /pics/bild1.jpeg in meinen browser ein (ohne session id, etc) dann wird im normalfall dieses bild auch angezeigt. das möchte ich vermeiden, da es nach meinem geschmack eine lücke ist

                Du scheinst nicht zu verstehen, was die Leute Dir hier im Thread sagen wollen. ;-)

                Natürlich ist das eine Lücke, wenn man das Bild direkt erreichen kann. Deswegen wurde Dir hier vorgeschlagen, ein PHP-Script zu schreiben, das die Bilder nach einer Überprüfung ausliefert. Dieses kann dann auch in der Session überprüfen, ob der Zugriff erlaubt ist. Im Prinzip sähe das dann so aus:

                1. /pics komplett für den HTTP-Zugriff sperren (Order deny, allow sowie Deny from all) - dann kann *niemand* mehr von außen auf die Bilder zugreifen.

                2. Bilder so in den HTML-Code einbinden:

                <img src="/pics.php/bild1.jpeg" ...>

                Dann wird also content.php aufgerufen und $_SERVER['PATH_INFO'] auf '/bild1.jpeg' gesetzt.

                Der Witz ist nun, dass sich das PHP-Script 'pics.php' darum kümmern muss, die Bilder an den Browser zu schicken, d.h. bei jedem Zugriff auf ein Bild wird das PHP-Script selbst ausgeführt und kann den Zugriff überprüfen.

                1. Das Script, das die Dateien ausliefert, sieht dann in etwa so aus:
                <?php  
                  
                // =================================================================  
                // Konfiguration  
                // =================================================================  
                // Alle Pfade sind relativ zum Verzeichnis in dem sich content.php  
                // befindet. Das '/pics' angefügt ist WICHTIG, damit man mit diesem  
                // Script nicht Zugriff auf *alle* Rohdaten hat.  
                $basePath = realpath (dirname (__FILE__).'/pics');  
                  
                // Erlaubte Dateiendungen  
                $allowedExtensions = array ('.jpeg', '.jpg', '.png', '.gif', '.pdf');  
                  
                // MIME-Typ-Mappings  
                $mimeMappings = array (  
                  '.jpeg' => 'image/jpeg',  
                  '.jpg' => 'image/jpeg',  
                  '.png' => 'image/png',  
                  '.gif' => 'image/gif',  
                  '.pdf' => 'application/pdf'  
                );  
                // =================================================================  
                  
                // 1. Schritt: Sitzung starten und überprüfen, ob Zugriff mit der aktuellen  
                // Sitzung überhaupt zulässig ist  
                session_start ();  
                  
                if (!isset ($_SESSION['access'])) {  
                  Header ('HTTP/1.1 403 Forbidden');  
                  exit;  
                }  
                  
                // 2. Schritt: $_SERVER['PATH_INFO'] holen und damit den Pfad des  
                // auszuliefernden Bildes  
                // $path enthält dann sowas wie '/..../pics/bild1.jpeg'  
                $path = $basePath.$_SERVER['PATH_INFO'];  
                  
                // 3. Schritt: Sicherheitsüberprüfung: realpath() nutzen und dann  
                // prüfen, ob das Ergebnis wieder mit dem gleichen Basispfad anfängt  
                $path = realpath ($path);  
                if ($path === false || substr ($path, 0, strlen ($basePath)) != $basePath) {  
                  Header ('HTTP/1.1 404 Not found');  
                  exit;  
                }  
                  
                // 4. Schritt: Weitere Überprüfung: Ist das eine Datei, die wir ausliefern  
                // wollen?  
                if (!is_file ($path)) {  
                  Header ('HTTP/1.1 404 Not found');  
                  exit;  
                }  
                  
                // 5. Schritt: Dateiendung überprüfen  
                $file = basename ($path);  
                $pos = strrpos ($file, '.');  
                if ($pos === false) {  
                  // Keine Dateiendung  
                  Header ('HTTP/1.1 404 Not found');  
                  exit;  
                }  
                $extension = substr ($file, $pos);  
                if (!in_array ($extension, $allowedExtensions)) {  
                  // Dateiendung nicht zulässig  
                  Header ('HTTP/1.1 404 Not found');  
                  exit;  
                }  
                  
                // 6. Schritt: Korrekten MIME-Type senden  
                $mimeType = $mimeMappings[$extension];  
                Header ("Content-Type: $mimeType");  
                  
                // 7. Schritt: Die Datei selbst senden  
                readfile ($path);  
                  
                ?>
                

                Bitte beachte, dass das nur die Ausgangsbasis für eine mögliche Implementierung darstellt und dass man das ganze auch gut erweitern kann. Allerdings habe ich hier schonmal aufgeführt, was mindestens an Sicherheitschecks in so ein Script hinein müsste. Mögliche Angriffe auf so ein Script wären (damit Dir klar ist, warum die Checks drin sind):

                * Auslieferung einer beliebigen Datei im gesamten Dateisystem, indem
                   man z.B. http://irgendwas/pics.php/../../../../datei aufruft. Dies
                   wird durch die realpath()-Abfrage unterbunden: realpath() löst immer
                   den gesamten Dateinamen auf, d.h. wenn man zum Beispiel als Angreifer
                   http://irgendwas/pics.php/../../../../../../../../../etc/passwd aufruft,
                   um /etc/passwd lesen zu können, dann steht nach dem realpath()-Aufruf
                   in $path eben '/etc/passwd' direkt drin. Und dann kann man mit dem
                   Vergleich, ob $path mit $basePath anfängt, abfragen, ob der Pfad denn
                   wirklich noch in dem erlaubten Pfad enthalten ist oder nicht.

                [realpath() wird auf den Inhalt von $basePath übrigens nur deshalb
                   angewendet, damit man das ganze hinterher auch brauchbar vergleichen
                   kann als String. Es gibt Situationen, in denen der Vergleich, dass
                   $path mit $basePath anfängt immer fehlschlagen würde, wenn man
                   realpath() ganz am Anfang nicht schon auf den Inhalt von $basePath
                   anwendet.]

                * Auslieferung des Quellcodes einer PHP-Datei, zum Beispiel der Datei,
                   in der die Datenbankzugriffsdaten drin stehen. Dies wird durch zwei Dinge
                   unterbunden:

                1) $basePath wird auf das '/pics'-Verzeichnis direkt gesetzt und nicht
                      auf das gesamte Webroot.

                2) Die Dateiendungen werden gegen eine Liste von erlaubten Dateiendungen
                      gematcht. Damit werden nur Dateien ausgeliefert, von denen man sich
                      sicher ist, dass die Auslieferung der Datei selbst keine
                      Sicherheitsproblematik darstellt.

                * Zugriff einer fremden Person auf die Dateien. Dies wird von vorne herein
                   damit unterbunden, dass als allererstes der Zugriff auf die Session
                   geprüft wird.

                Wenn Du nun die Situation hast, dass nicht alle Dateien in /pics beschränkt  sein sollen, würde ich Dir dennoch empfehlen, das einfach in zwei verschiedene Verzeichnisse aufzuteilen: Eines, das für alle zugänglich ist über normales HTTP und eines das über normales HTTP gesperrt ist und wofür man das Script braucht. Das ist die sauberste Lösung für dieses Problem.

                Ansonsten: Bitte versuche, das Script durchzugehen und Zeile für Zeile zu verstehen, was es da macht und warum es das so macht. Bitte versuche erst dann, am Script herumzubauen, oder Du läufst Gefahr, Dir eine riesige Sicherheitslücke aufzureißen.

                Oh, achja, das Script ist aus dem Kopf und nicht getestet, eventuelle Syntaxfehler durch vergessene ; bitte ich zu verzeihen.

                Viele Grüße,
                Christian

                1. echo $begrüßung;

                  Noch ein paar Ergänzungen.

                  1. /pics komplett für den HTTP-Zugriff sperren (Order deny, allow sowie Deny from all) - dann kann *niemand* mehr von außen auf die Bilder zugreifen.

                  Noch besser ist es, das pics-Verzeichnis gleich außerhalb des DocumentRoot abzulegen, dann benötigt man auch keine HTTP-Zugriffssperre, die mit einem versehentlichen Löschen der .htaccess nicht mehr vorhanden ist. Und da der OP die <Directory>-Direktive des Apachen verwenden kann, hat er höchstwahrscheinlich auch Einfluss auf die Verzeichnisstruktur. Lediglich das Auslieferungsscript muss unterhalb des DocumentRoot liegen oder es muss eine andere Apache-Konfiguration dafür sorgen, dass es aufgerugen wird. Der Möglichkeiten gibt es viele.

                  // Erlaubte Dateiendungen
                  $allowedExtensions = array ('.jpeg', '.jpg', '.png', '.gif', '.pdf');

                  // MIME-Typ-Mappings
                  $mimeMappings = array (
                    '.jpeg' => 'image/jpeg',
                    '.jpg' => 'image/jpeg',
                    '.png' => 'image/png',
                    '.gif' => 'image/gif',
                    '.pdf' => 'application/pdf'
                  );

                  Das kann man optimieren. Du hast hier eine doppelte Datenhaltung. Einmal stehen die Endungen in $allowedExtensions, zum anderen genau die gleichen nochmal als Schlüssel in $mimeMappings. Statt

                  if (!in_array ($extension, $allowedExtensions)) {

                  kann man

                  if (!isset($mimeMappings[$extension])) {

                  oder

                  if (!array_key_exists($extension, $mimeMappings)) {

                  notieren und sich $allowedExtensions sparen.

                  1. Bilder so in den HTML-Code einbinden:
                    <img src="/pics.php/bild1.jpeg" ...>
                    Dann wird also content.php aufgerufen und $_SERVER['PATH_INFO'] auf '/bild1.jpeg' gesetzt.

                  Hier wäre zu prüfen, ob das Feature PathInfo überhaupt verfügbar ist. Im Apachen kann es mit AcceptPathInfo beeinflussbar. Im IIS habe ich unterschiedliche Erfahrungen gemacht, kann aber grad nicht genau benennen, unter welchen Umständen PathInfo verfügbar ist oder nicht.
                  Alternativen zu PathInfo wären der Querystring bzw. GET-Parameter und eine URL-Umschreibung mit mod_rewrite. Letztere ist vor allem dann sinnvoll, wenn bereits vorhandene Links nicht durch das Einfügen des .php geändert werden sollen. Eine Alternative zu mod_rewrite wäre ForceType, mit der man ein Script namens pics (ohne Endung) durch den PHP-Handler schicken kann. Normalerweise ist ja nur die Dateiendung .php konfiguriert, durch PHP behandelt zu werden.

                  echo "$verabschiedung $name";

                2. Hallo,

                  gebe ich nun die domain + /pics/bild1.jpeg in meinen browser ein (ohne
                  Du scheinst nicht zu verstehen, was die Leute Dir hier im Thread sagen wollen. ;-)

                  definitiv, da hat wohl das ganze forum an mir vorbeigeredet, aber jetzt ists klar.

                  1. Bilder so in den HTML-Code einbinden:

                  <img src="/pics.php/bild1.jpeg" ...>

                  Dann wird also content.php aufgerufen und $_SERVER['PATH_INFO'] auf '/bild1.jpeg' gesetzt.

                  will jetzt nich noch riesig ins datail gehen, aber hab die form script.php/filename.ending noch nicht gesehen. als mir das kleine lichtlein aufging dach ich nämlich man sollte es mit src="auslieferdatei.php?path=pfadzumbild.jpeg" machen. ist da ein prinzipieller unterschied, oder ist das im grunde das gleiche?

                  danke an alle für eure geduld...

                  grüße
                  c.

                  1. Hallo,

                    will jetzt nich noch riesig ins datail gehen, aber hab die form script.php/filename.ending noch nicht gesehen. als mir das kleine lichtlein aufging dach ich nämlich man sollte es mit src="auslieferdatei.php?path=pfadzumbild.jpeg" machen. ist da ein prinzipieller unterschied, oder ist das im grunde das gleiche?

                    Naja, ich finde script.php/sonstwas irgendwie schöner als script.php?path=sonstwas, aber vom Verarbeitungsprinzip ist das vollkommen egal. Du musst halt dann $_GET['path'] statt $_SERVER['PATH_INFO'] verwenden.

                    Ansonsten siehe noch die Anmerkungen von dedlfix.

                    Viele Grüße,
                    Christian

          3. Hello,

            jo, das wär ja au super... wenn mir jemand sagt, wie ich SetEnvIf aus ner Datei erstellen kann, würd mir des ausreichend helfen

            Vermutlich kaum, ohne ein zusaetzliches Apache-Modul selbst zu schreiben ...

            hoffentlich hast du da nicht recht. is eigentlich schon der Lösungsansatz, den ich gerne fahren würde, da es zum einen dem chef seine Vorgabe is und da zum anderen so einfach generell alle möglichen Dateien geschützt sind, nich nur die pdfs...

            Du bringst da immer noch Ursache und Wirkung durcheinander.
            HTTP ist von seiner Grundidee her zustandslos (stateless). Du willst Dir aber einen Zustand merken (nämlich "logged") und kannst dafür am besten eine Session benutzen. Dadurch wird der gesamte Prozess dann zustandsbehaftet (stateful).

            Auf Manipulationen am Server sollte man verzichten, wenn es schon Methoden gibt, die für das gewünschte Verhalten sogar vorgesehen sind. Und was bringt es Dir denn, wenn Du nun im Environment einen Parameter mehr bekommst, der dann doch wieder vom Script abgefragt werden muss?

            Ausnahme wäre das Hinzufügen des User-Passwortes für den Zugang per .htaccess bei der CGI-Version von PHP/Apache. Das wird standardmäßig nicht an das Script ausgeliefert und kann ggf. mittels einer Regel durch Mod_Rewrite zusätzlich ins Script importiert werden (dem Environment hinzugefügt werden).

            Liebe Grüße aus Syburg bei Dortmund

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
  2. Hello,

    Code würde ungefähr so aussehen:

    SetEnvIf $_SESSION["access"] access_granted
    <Directory /topsecret>
        Order Deny,Allow
        Deny from all
        Allow from env=access_granted
    </Directory>

    Du schmeißt mit der Henne nach dem Ei.

    Erst wickelt der Server seine Arbeit ab und erstellt das Environment und dann wird die Kontrolle und dieses Environment an das PHP-Runtime (Modul) oder den PHP-Prozess (CGI) übergeben. Beim Prozess ist es sogar noch viel klarer getrennt. Der wird nämlich erst gestartet, wenn das Environment erstellt ist.

    Liebe Grüße aus Syburg bei Dortmund

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de