Announcement

Collapse
No announcement yet.

PHP Konzept für Passwort geschützten Member-Bereich

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • PHP Konzept für Passwort geschützten Member-Bereich

    Hallo @all,

    ich möchten einen passwortgeschützten Bereich für Mitglieder auf meiner Hompage selbst programmieren.
    Welches Konzept benutzt man, um dieses zu realisieren.

    Meine vorgehensweise ist:

    login-Formular mit einer funktion check_user die die userid aus der Datenbank zurück gibt (bei Erfolg sonst false)

    Dann eine Login-Funktion, die zum eingelogged User die Session-ID in die Datenbank schreibt.

    Dann eine Funktion isLoggedIn, die immer die true zurückgibt, wenn die session_id in der user tabelle der datenbank steht.

    Dann eine Logout funktion, die die session id in der user-datenbank wieder auf null setzt.

    Soweit funktioniert alles... und meine Content-Seiten, die ich dann schützen möchte muss ich in einen If-Konstrukt setzen und dann auf isLoggedIn() abfragen.
    Falls nicht einen anderen include() machen...

    Ist das Konzept kritisch für User die nicht den Logout Button benutzen?

    Wie machen das große Foren oder System wie Nuke, phpbb... etc
    und ander message boards in php geschrieben...

    Für Kommentare und Anregungen wäre ich dankbar..

  • #2
    Das Konzept hat ein paar Schwächen, eine davon hast Du selbst schon angesprochen: User, die sich nicht ausloggen. Die Gefahr ist zwar nicht riesig, aber sie ermöglicht durchaus Session-Hijacking und kann (je nach Aufbau) auch zu Problemen beim wieder einloggen führen.<br />
    Ein anderes Problem is der Aufwand, den Du mit if und isLogged betreiben willst. Änderst Du irgendwann einmal etwas an deiner Authenfifizierung, dann mußt Du alle Scripte (Seiten) ändern.<br />
    Ich stand einmal vor einem ähnlichen Problem für ein Portal und habe es über 3 Klasen gelöst.<br />
    AuthUser() lies die Logindaten des Users bei der Anmeldung aus, berechnet für den User eine eindeutige ID und trägt die relevaten Daten, die eindeutige ID und die IP des Users in eine HEAP-Tabelle (sehr schnell, da nur im Arbeitsspeicher des DB-Servers) ein.<br />
    Die zweite Klasse OnlineUser() wird über die eindeutige ID des Users instaniert. Sie schaut in der HEAP-Tabelle nach, ob diese ID existiert und von der gleichen IP aufgerufen wird und im Erfolgsfalle gibt sie z.B. den Usernamen zurück und erhöhte einen Timestamp in der Tabelle. Bei Mißerfolgt gibt sie wahlweise false zurück, oder bricht die Scriptverarbeitung komplett ab.<br />
    Die letzte Klasse GarbageCollection() wird mittels Zufall ab und an bei der Initialisierung eines Users gestartet und bereinigt die Tabelle um alle Einträge, deren Timestamp eine gewisse Dauer veraltet sind, somit wird jemand auch dann ausgeloggt, wenn er dies nicht manuell tut.<br />
    Das hatte den Vorteil, daß ich in allen Seiten nur ie Klasse User einbinden mußte, die ich je nach Wunsch beliebig zentral ändern kann, ohne später an die Scripte zu müssen (was auch schon ein paar Mal der Fall war) und es gibt keine "Datenbankleichen" durch dei GarbageCollection().<br />
    Im Endeffekt gehörte zu dem portal zwar noch mehr (Anwenderrechte, Modulberechtigungen, virtuelle Ordner, dynamische Authentifizierung auf statischen HTML-Seiten), aber im Grundprinzip basierte die komplette Anwendung auf diesen 3 Klassen

    Comment


    • #3
      Hallo Xafford,

      dank für die schnelle Antwort...
      Hört sich interessant an mich würden dann noch ein paar Details interessieren.
      Interessante Aspekte sind der zusätzliche Vergleich mit der IP um Session-Spoofing zu verhindern...
      und dass man nur einmal die DB abfragen muss.

      zu den Fragen die eindeutige ID von der Du sprichst, ist dass die Session-ID oder eine selbstgenerierte?

      Tabelle in den Heap schreiben? $_Session ist ein Key Value Pair im Heap meinst Du das?
      Wievel kann man in der Tabelle speicher ohne den Server in die Knie zu bringen würden Objekte einer Klasse User Sinn machen?

      Wie unterscheidet man jetzt ob ein User eingelogged ist oder nicht! So wie ich das verstanden habe, würde es in der OnlineUser() funktionieren... würde aber bedeuten, dass ich dies auch for jede Seitenaufruf bauen müsste ähnlich wie isLoggedIn.

      Frage über Frage finde diesen Ansatz aber sehr interessant. Vielleicht könntest Du mir noch ein paar Details erleutern und Tips geben auf was man achten sollte.

      Vielen Dank schon mal...

      Comment


      • #4
        Hallo,<br />
        <br />
        Ich versuche das Ganze noch einmal detaillierter zu erläutern, bei ein paa rPunkten haben wir uns Mißverstanden.

        Die eindeutige ID ist eine selbst genereierte. Ich hätte hier zwar auch auf Sessions zurückgreifen können, wollte es aber möglichst portabel halten und brauchte nicht die gesamte Funktionalität von Sessions. Der Key wird eigentlich nur rein per Zufall erzeugt durch eine Methode der Klasse AuthUser(). Diese Funktion sieht wiefogt aus:<br />
        <pre>
        function __key() {
        if (!@ mt_srand((double) microtime() * 1000000)) {
        @ srand((double) microtime() * 1000000);
        }
        $r = (@ mt_rand(mt_getrandmax()) ? @ mt_rand(mt_getrandmax()) : @ rand(getrandmax()));
        if ($r) {
        return ($this->__key = md5(uniqid($r, TRUE)));
        } else {
        trigger_error(1004, E_USER_WARNING);
        return false;
        }
        }

        </pre>

        Dieser Key wird dann zusammen mit dem Usernamen und der IP und einem Timestamp in der DB gespeichert, wobei dieer Key Primary ist. Weiterhin habeich noch die Email des Users in der DB für Bans (diese werden über Usernamen, IP oder Email durchgefürt, da es ein öffentliches und moderiertes Portal ist und man Trolle schnell ausschließen muß).<br />
        AuthUser() gibt dann nur den Key zurück, mit dem man dann beliebig weiterarbeiten kann, z.B. in Cookiesoder als GET-Variable. AuthUser() tut dann nichts weiter.sondern die Kontrolle geht an OnlineUser() über.<br />
        OnlineUser() bekommt bei der Initialisierung den Key übergeben und überprüft mit einer Methode AuthRestore(), ob in der Online-Tabelle, die besagte HEAP-Tabelle, einUser mit diesem Key existiert und dieser User (oder seine IP oder seine Email) nicht gebannt wurde. Ist der User rechtmäßig vorhanden, so wird die Klasse endgültig erstellt und bietet Zugriff auf die Userdaten. Schlägt diese Überprüfung fehlt, dann zerstört sich die Klasse selbst und bricht optional die komplette Scriptverarbeitung ab, ein nicht eingeloggter user bekomt dann also nur eine leere Seite (oder alternativ eine Fehlermeldung) zu sehen. Dies passiert auf jeder Seite, die Authentifizierung erfordert und bei jedem Aufruf automatisch.<br />
        Diese Klasse kann man bequem entweder manuell in jeder Seite includieren, oder aber per auto_prepend_file() automatisch eininden lassen, ohne auch nur eine einzige Seite ändern zu müssen. Auf jeden Fall erspart es einem den kompletten Code in ein IF-Konstrukt packen zu müssen, was recht fehlerträchtig sein kann. Wenn man dies trotzdem wollte, dann ginge das aber auch, ungefähr so:<br />
        <pre>
        if( ( $user = new OnlineUser ( $_GET [ 'SKEY' ] ) ) ) {
        // Seitencode
        }
        </pre>
        <br />
        Was die HEAP-Tabelle angeht, so liegt ein Mißverständnis vor, die HEAP-Tabelle wird von einer MySQL-DB bereitgestelt. HEAP ist neben MyISAM und InnoDB ein weiterer Tabellentyp und hat den Vorteil, daß er komplett im Speicher vrgehalten wird und somit sehr schnell arbeitet im Vergleich zu anderen Tabellentypen. Solt der Arbeitsspeicher nicht ausreichen, dann greifen die normalen Paging-Methoden des Betriebssstems, der Sppeicher läuft also nicht über. Trotzdem sollte man mit HEAP nur relativ kleine Tabellen nutzen. In meinen Augen war es eben sinnvoller eine kleine schlanke und vor allem statische Tabelle (also nur benötigte Spalten und keine dynamischen) zu nutzen, die ständig abgefragt wird, als die große Userdatenbank.<br />
        Mit dem Einwand, daß OnlineUser() ähnlich isLoggedIn() zu benutzen is thast Du recht, nur hast Du eine bessere Kapselung mit einer Klasse, zumal die Datenbankbehandlung noch einmal von OnlineUser() isolirt in einer Klasse liegt und man somit jederzeit von einer MySQL-DB auf eine andere Datenbank oder sogar reinen Dateien wechseln kann ohne Änderungen am Code

        Comment


        • #5
          Hallo,

          danke für Deine ausführlich Beschreibung.
          Ich habe bis jetzt ein Mischung aus beiden Konzepten realisiert.
          Nach ein bisschen forschen habe ich auch Herausgefunden, was Heap-Tabellen sind danke für den Tipp =).

          1.) Eine Daten-Bank Klasse hatte ich auch schon geschrieben, um die Technik zu kapseln und bei einem eventuellen wechsel die Daten Bank-Klasse nur ändern zu müssen.

          2.) habe ich dann eine useronline Klasse geschrieben in Anlehnung nach Deinem Konzept.
          Diese Klasse hat bis jetzt die 2 Funktionen AuthentikateUser($user,$pw)
          Diese check, ob der User in der Datenbank ist und schreibt falls vorhanden in die heap-tabelle. Bei Erfolg gibt Sie die Session-ID zurück (Habe mich doch für die Session-Id entschieden).
          In der Heap-Tabelle ist dann der Eintrag mit Session-Id kombiniert mit IP.
          Dann habe ich mein berühmte Funktion isLoggedId($id) die schaut, ob die jetzige Session kombiniert mit der IP in meiner Heap-Tabelle eingetragen ist. Falls ja gibt es zugang auf die Seite.
          das mit auto_prepend_file() konnte ich nichts anfangen. Ich habe dazu nur Einstellungen in der PHP.ini gefunden, was leider nicht in Frage kommt, wenn man bei einem kommerziellen Hoster ist.
          Deshalb sieht meine Seit im Moment so aus

          include("lib.php");
          session_start();
          $cuser = new onlineuser();
          if(isset($_POST['user']) && isset($_POST['pwd']))
          { extract($_POST);

          $userkey = $cuser -> authuser($user,$pwd);
          }

          if($cuser->isLoggedIn(session_id()))
          {

          include("innercontent.php");
          }else{
          print "bin wohl nicht eingelogged";
          include("login.php");
          }

          In der innercontent.php kann ich dann die attribute von meinem User auslesen und benutzen, wie z.B.: username, ip, email etc und user level. Ich habe es zu Thema verbannen so gemacht, dass ein userlevel von 0 ein gebannter user ist.

          in meiner lip.php
          besteht aus
          db.php
          onlineuser.php.
          Ein auslog-Funktion muss ich noch schreiben.
          Was gilt eigentlich für den Fall, fals sich ein user an zwei Rechner einlogged.
          Weil meine TempTableAufräum-Funktion muss ich auch noch schreiben, die alle alten User aus der Heap-Tabelle kickt.

          Was meinst Du zu meinem Zwischenstand?
          Vielen Dank schon mal für die Hilfe =

          Comment

          Working...
          X