Fabienne: mit PHP die .htaccess öffnen???

Ich habe ein "Mini-Portal", bei dem sich User im php-Formular einloggen können. Die User sind in einem Array gespeichert (also kein SQL o.ä.).

Nun gibt es aber das Problem, dass USer von außen dennoch die Bilder, pdf's usw. abrufen können, da ja nur dir *.php-Dateien geschützt sind. Wenn ich eine .htaccess mit user und Passwort aufschalte wäre natürlich alles geschützt (mehr oder weniger sicher == egal), aber die User müßten sich dann 2x anmelden.

Gibt es also eine Möglichkeit in php die in php für OK bewerteten User+Passworte an die htaccess weiterzureichen und dem aktuellen Client den Zugriff auf die Verzeichnisstruktur zu gewähren?????

Oder gibt es in php die Möglichkeit (ähnlich der htaccess) ganze Verzeichnisse und deren Unterstrukturen zu schützen???

DANKE!!

  1. Hallo,

    Oder gibt es in php die Möglichkeit (ähnlich der htaccess) ganze Verzeichnisse und deren Unterstrukturen zu schützen???

    Ja. Das Prinzip:

    Die gegen aussen "sichtbare URL" stimmt nicht ueberein mit
    dem Dateisystem auf dem Server, und die Dateien liegen
    in einem Verzeichnis, das nicht via HTTP zugaenglich ist.

    Sichtbare URL:
    http://www.example.com/privat/bilder/foto1.jpg
    Aufgerufen wird aber (unsichtbar):
    http://www.example.com/privat.php?pfad=bilder/foto1.jpg
    Wenn der Benutzer berechtigt ist (Session/Cookie oder so),
    und wenn der Pfad in Ordnung ist (Sicherheits-Pruefungen
    unbedingt notwendig!), dann schickt das PHP-Skript
    die HTTP-Header (hier: image/jpeg) und danach den Inhalt
    der Datei, z.B. mit fpassthru() oder readfile().

    Bei nicht berechtigten Usern gibt's eine Fehlermeldung
    oder eine Umleitung auf die Login-Seite.

    Stichworte:
    * search engine friendly URLs
    * Apache mod_rewrite
    * PHP readfile, fpassthru
    * Sessions

    Gruesse,

    Thomas

    1. Hello,

      die Beschränkungen über .htaccess und .htpasswd (oder wie man sie sleber nennt) gelten i.d.R. nur für den direkten Zugriff über HTTP auf das Verzeichnis. Wenn nun aber das PHP-Script zugreift (also das Runtimesystem von PHP) dann gelten nur die "normalen" Beschränkungen des Betriebssystems, also rwx ...

      Der Deamon (PHP-Runtime) wird dabei wie ein normaler User behandelt und wickelt mit SEINEN Rechten den Auftrag ab.

      Wenn man im Script also nicht dafür sorgt, dass nur autorisierte User zugreifen können, ist das eine schöne Lücke.

      Grüße

      Tom

  2. Wie funzt das mit dem header()?? Ich habe das so ähnlich schon mal versucht, hat aber nicht geklappt.
    Wie wäre es, den User via header("LOCATION: username:passwort@test.php") auf die Seite Test zu schicken, die Seite test.php leitet sofort weiter an header("LOCATION: seite.php"). Dann dürfte der User eigenlich den Username und das Passwort gar nicht zu sehen bekommen... Problem: Es funzt nicht, da der Client in diesem Fall der Server war...

    Kann mir jemand die Möglichkeit mit dem Bilder via header senden näher erläutern? Evtl. auch nen Beispiel-Code??

    Wäre sehr verbunden. Vielen Dank.

    1. Hallo,

      Wie funzt das mit dem header()??

      RTFM:
      http://www.php.net/manual/de/function.header.php

      Ich habe das so ähnlich schon mal versucht, hat aber nicht geklappt.

      Vermutlich hattest Du _vor_ dem Header schon etwas an den
      Browser geschickt, und sei es nur ein Leerzeichen oder Zeilenumbruch.
      http://www.dclp-faq.de/q/q-fehler-header.html

      Wie wäre es, den User via header("LOCATION: username:passwort@test.php") auf die Seite Test zu schicken, die Seite test.php leitet sofort weiter an header("LOCATION: seite.php"). Dann dürfte der User eigenlich den Username und das Passwort gar nicht zu sehen bekommen...

      Das ist Unfug.

      Und es enthaelt einen groben Fehler: Die URL muss absolut und vollstaendig sein,
      also mit "http://" beginnen:
      header('Location: http://www.example.com/seite.php');

      Anders als bei FTP ist es bei HTTP soviel ich weiss nicht vorgesehen,
      den Benutzernamen und das Kennwort in die URL reinzupacken.
      (Ich weiss, dass es in den meisten Browsern trotzdem funktioniert.)
      Es ist auch sehr fahrlaessig, denn die Adresse bleibt an diversen
      Orten haengen, z.B. im Cache, in der History, im Adresszeilen-Gedaechtnis
      des Browsers, in Proxy-Servern u.s.w.

      Wenn die Sicherheit sehr wichtig ist, sollte man sowieso nicht HTTP,
      sondern HTTPS (SSL) verwenden.
      Auch bei GET- und POST-Anfragen wird das Passwort unverschluesselt
      uebermittelt.
      Bei GET ist es genauso unsicher, wie mit der obigen "@" Methode, weil
      das Passwort sichtbar ist.

      Befasse Dich intensiver mit Sicherheit im allgemeinen und Passwortschutz-
      Loesungen in PHP sowie Sessions im speziellen.
      _Einigermassen_ sicher waere es z.B., wenn sich der Benutzer
      ueber ein POST-Formular einlogt, dann eine Session-ID kriegt,
      und fuer alle folgenden Anfragen die Session-ID uebergeben wird.
      Die Session-ID wird ueblicherweise in einem Cookie gespeichert,
      wenn das nicht moeglich ist, wird sie an alle URLs drangehaengt.

      Sobald der Benutzer sich "abmeldet", oder nach einer vorbestimmten
      Zeit der Inaktivitaet, wird die Session geloescht, und auch jemand,
      der zufaellig an die Session-ID kommt, kann nichts mehr damit anfangen,
      weil sie nicht mehr gueltig ist.

      Problem: Es funzt nicht, da der Client in diesem Fall der Server war...

      Das sollte keine Rolle spielen.

      Kann mir jemand die Möglichkeit mit dem Bilder via header senden näher erläutern? Evtl. auch nen Beispiel-Code??

      <?php
      $verlangt=intval($_GET['nr']);
      unset($bild); // Zur Sicherheit, falls register_globals on ist...
      unset($pfadzumbild); // dito

      $bild[0]="pfad/zum/null.gif"; // Transparentes 1x1 Pixel GIF
      $bild[1]="pfad/zu/bild1.jpg";
      $bild[2]="pfad/zu/bild2.gif";
      if (isset($bild[$verlangt])) // d.h. wenn ein zulaessiges Bild verlangt wird
        { $pfadzumbild=$bild[$verlangt]; }
      else
        { $pfadzumbild=$bild[0]; } // Transparentes GIF ausgeben

      $bildinfos=getimagesize($pfadzumbild);
      $bildtypnr=$bildinfos[2];

      $contenttype[1]='image/gif';
      $contenttype[2]='image/jpeg';
      $contenttype[3]='image/png';

      header("Content-Type: $contenttype[$bildtypnr]");
      readfile($pfadzumbild);

      ?>

      Kannst Du hier ausprobieren:

      http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=1
      http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=2
      http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=99

      PHP-Manual-Kapitel zu den verwendeten Funktionen getimagesize() und readfile():

      http://www.php.net/manual/en/function.getimagesize.php  englisch, aktuell
      http://www.php.net/manual/de/function.getimagesize.php  deutsch, unvollstaendig

      http://ch.php.net/manual/en/function.readfile.php englisch, aktuell
      http://ch.php.net/manual/de/function.readfile.php deutsch

      Testen, welchen HTTP-Header der Server schickt, kannst Du z.B. mit:
      http://cgi.w3.org/cgi-bin/headers

      Gruesse,

      Thomas

      1. Hab den Code so übernommen, allerdings meine Bilder in einen nicht öffentlichen webordner gestellt. Rauskommen tut nur ein riesen Buchstaben-Zahlensalat...

        Was mach ich falsch?? Muss ich zuerst noch ne html-Seite generieren, in dem ein img-Tag steht??

        1. Hallo,

          Hab den Code so übernommen,

          Wirklich so, 1:1?
          Ohne etwas vorher oder nachher auszugeben?
          Er muss ganz genau mit der spitzen Klammer von
          <?php
          oder
          <script language="php">
          anfangen und mit der spitzen Klammer von
          ?>
          oder
          </script>
          aufhoeren.

          Ausser den beiden Zeilen:

          header("Content-Type: $contenttype[$bildtypnr]");
          readfile($pfadzumbild);

          (und ggf. weiteren Headern) darf _nichts_ an den Browser
          geschickt werden.

          allerdings meine Bilder in einen nicht öffentlichen webordner gestellt.

          Sollte keine Rolle spielen, weil PHP ja ueber's Dateisystem
          auf die Datei zugreift und nicht via HTTP.

          Rauskommen tut nur ein riesen Buchstaben-Zahlensalat...

          Also gibt PHP offenbar etwas aus ;-)
          Das ist schonmal gut.

          Welcher Browser? Welches Betriebssystem?

          Wie faengt der Buchstabensalat an?

          Was siehst Du bei meinen Beispielen?
          http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=1
          http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=2

          Was sagt der HTTP Head Service bei Dir?
          http://cgi.w3.org/cgi-bin/headers

          Wie hast Du die Pfade zu den Bildern angegeben?

          Muss ich zuerst noch ne html-Seite generieren, in dem ein img-Tag steht??

          Nein. Siehe meine Beispiele.
          Die funktionieren bei mir problemlos in Mozilla 1.2.1 und Konqueror 3.1.1 (SuSE Linux).

          Gruesse,

          Thomas

          1. Dieses Problem habe ich ja schon gelöst... Hatte HTML-Code vor dem header ausgegeben... Anfänger-Fehler...

            Aber wie kann ich jetzt in einem html-Dokument diese Bilder verwenden??

            Die Bilder auf deinen Versuchsseiten sehe ich, allerdings nur Bilder, kein HTML.

      2. Oh ja, ich habe meinen Fehler entdeckt:

        Habe vor dem header schon html ausgegeben.

        Wie kann ich dann diese Bilder via Bildschleuse in bestehenden html-Code implementieren??

        1. Hallo,

          Oh ja, ich habe meinen Fehler entdeckt:
          Habe vor dem header schon html ausgegeben.

          Aber, aber!
          In weiser Voraussicht hatte ich Dir doch bereits den Link zu
          http://www.dclp-faq.de/q/q-fehler-header.html
          gepostet.

          Das Bild-Durchschleuser-Skript darf _gar_kein_ HTML ausgeben.
          Auch nicht im Fehlerfall.
          Weil seine Ausgabe ja ein Bild sein soll.

          Wie kann ich dann diese Bilder via Bildschleuse in bestehenden html-Code implementieren??

          Wie ein normales Bild.
          <img src="http://www.tiptom.ch/tests/phpssi/bildschleuse.php?nr=1" alt="Foto einer Uhr" width="207" height="300">

          Das ganze Gebastel dient ja dem Passwortschutz.
          Wie gesagt, wuerde ich das mit Sessions loesen.

          Im Fall, dass der Browser kein Cookie akzeptiert, wird die Session-ID
          einfach an die URL des Bild-Durchschleuser-Skripts angehaengt.

          <img src="bildschleuse.php?nr=1&PHPSESSID=xyz123abc978" alt="...">

          Beachte:

          • Das Ampersand (&) muss in HTML mit & codiert werden
          • je nach Einstellungen von PHP (session.use_trans_sid, url_rewriter.tags)
              geschieht das Anhaengen der Session-ID an relative URLs auch ganz automatisch,
              sonst musst Du es bei jedem Bild "von Hand" machen. Dabei gut zu wissen:
          • Der String "PHPSESSID=xyz123abc978" (oder so) ist in der Konstanten
              SID verfuegbar.
          • bei einer falschen Session-ID (d.h. bei einem "Einbruchsversuch")
               sollte das Durchschleuser-Skript natuerlich nicht das richtige Bild,
               sondern ein Transparentes GIF oder ein "Nicht-Erlaubt"-Bild ausgeben.

          Noch etwas Lektuere fuer den Feieraben:
          http://www.dclp-faq.de/ch/ch-security.html
          http://www.dclp-faq.de/ch/ch-version4_session.html
          http://www.php.net/manual/en/ref.session.php

          Gruesse,

          Thomas

          1. VIELEN DANK!!!!!!!

            P.S. Ich arbeite bereits mit session, da ich ne Benutzerabfrage drin habe, dann in einer globalen Variable $globale_variable den Nutzer usw. abspeicher und den dann (ohne Cookie) via URL von Seite zu Seite weiterreiche.  Kann ich da eigentlich auch ne Verfallszeit wie bei einem Cookie einstellen, dass der USer maximal z.B. eine Stunde lang online sein kann und alle späteren Versuche abgewehrt werden, oder ist das größerer Programmieraufwand?

            Nochmals Danke für die "Bildschleuse".
            Noch was: Die Seite muss nicht 1000% sicher sein, sondern nur 100%ig.
            Also ist die session-Geschichte als Sicherheitslücke OK, aber ne Verfallszeit wäre ganz gut.

            1. Hallo,

              VIELEN DANK!!!!!!!

              Gerngeschehen.
              Ich habe dieses "Durchschleusen" als Prinzip schon ein paarmal
              empfohlen, aber um ehrlich zu sein, habe ich es heute zum ersten
              Mal selbst ganz konkret ausprobiert...
              War erfreut, zu sehen, dass es funktioniert. ;-)

              Ich arbeite bereits mit session, da ich ne Benutzerabfrage drin habe, dann in einer globalen Variable $globale_variable den Nutzer usw. abspeicher und den dann (ohne Cookie) via URL von Seite zu Seite weiterreiche.

              Dann hast Du dass Prinzip der Sessions noch nicht restlos begriffen.
              Der Witz an den Sessions ist gerade, dass Du _nur_ die Session-ID
              von Seite zu Seite weitergibst (mit Cookies ist nichtmal das notwendig).
              Alle anderen Variablen (Benutzername, Passwort, weitere persoenliche
              Daten, Voreinstellungen, was auch immer) bleiben auf der "sicheren Seite",
              naemlich auf dem Server, gespeichert, wo nur _Du_ (d.h. Dein Skript)
              darauf Schreib- und Lesezugriff haben.

              Lies mal:
              http://www.dclp-faq.de/q/q-sicherheit-parameter.html

              Also ist die session-Geschichte als Sicherheitslücke OK, aber ne Verfallszeit wäre ganz gut.

              So, wie Du es machst, ist es eine Sicherheitsluecke.

              Das "Restrisiko" besteht in der Uebernahme einer Session
              durch eine unberechtigte Drittperson.
              Bei Cookies ist das _relativ_ unwahrscheinlich
              (d.h. jemand muesste den Datenverkehr abhoeren),
              bei GET (Anhaengen an die URL) schon wahrscheinlicher
              (beides kann zum Problem werden bei Computern in Web-Cafes,
              Universitaeten und anderen gemeinsam genutzten Computern).

              Wenn die Benutzer sich diszipliniert ausloggen, und man
              anschliessend die Session loescht, vermindert das
              dieses Risiko.

              Die Verfallszeit ist in der PHP-Konfiguration geregelt:
              http://www.php.net/manual/en/ref.session.php
              und zwar mit den Einstellungen session.gc_maxlifetime
              und session.cookie_lifetime.
              Diese sind in der php.ini vordefiniert, aber Du kannst
              sie auch zur Laufzeit aendern mit ini_set():
              http://www.php.net/manual/en/function.ini-set.php

              Gruesse,

              Thomas

              P.S. habe nun mal endlich das Subject etwas angepasst...