Sebastian: Eine DB-Abfrage automatisch als $_SESSION-Werte speichern

Hallo Forumler,

für ein Login-System arbeite ich mit einer MySQL-Datenbank und Sessions.
Um nicht auf jeder Seite, wo dies nötig ist, die DB abzufragen, habe ich mir überlegt, ob die Möglichkeit besteht, beim Erst-Login, wo ich ja sowieso Benutzername und Passwort mit der DB abgleiche, gleich alle Werte auszulesen und diese als Session-Variablen abzuspeichern.

Natürlich könnte ich nun jeden einzelnen Wert meiner SQL-Abfrage als $_SESSION['foo'] abspeichern.

Aber gibt es vielleicht eine elegante Möglichkeit, dies zu automatisieren?

So nach dem Motto

$suche_SQL="SELECT * FROM beispiel_tabelle WHERE benutzer='$benutzer'";
      $suche_result=mysql_query($suche_SQL) OR die (mysql_error());
      $ergebnis=mysql_fetch_array($suche_result) OR die (mysql_error());
      mysql_close;

if($ergebnis['passwort']==$_POST['passwort']) {

while(im $ergebnis-Array Werte sind) {
          $_SESSION['DB-Feld']=$ergebnis['DB-Feld'];
        }
      }

War das halbwegs verständlich?

Im Voraus herzlichsten Dank und außerdem schöne Grüße -
Sebastian

  1. hi,

    Natürlich könnte ich nun jeden einzelnen Wert meiner SQL-Abfrage als $_SESSION['foo'] abspeichern.

    Aber gibt es vielleicht eine elegante Möglichkeit, dies zu automatisieren?

    durchlaufe das, was mysql_fetch_array() zurückliefert, in einer foreach-schleife, die dir key und value zurückliefert - und fügr damit die werte in die session ein.

    if($ergebnis['passwort']==$_POST['passwort']) {

    btw: es bietet sich an, dass passwort auch gleich in der mysql-query mit abzufragen. passt es nicht zum benutzernamen, gibt es keinen ergebnisdatensatz, damit bist du an dieser stelle schon fertig.

    btw2: benutzereingaben ungeprüft in eine query zu übernehmen, wie due es anscheinend derzeit machst, bietet sich hingegen natürlich gar nicht an. informiere dich mal über SQL injections, und was man dagegen tun kann (bzw. muss).

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo Wahsaga,

      durchlaufe das, was mysql_fetch_array() zurückliefert, in einer foreach-schleife, die dir key und value zurückliefert - und fügr damit die werte in die session ein.

      Also ungefähr so?:
            $suche_SQL="SELECT * FROM beispiel_tabelle WHERE benutzer='$benutzer'";
            $suche_result=mysql_query($suche_SQL) OR die (mysql_error());
            foreach((mysql_fetch_array($suche_result)) as $key => $value) {
              $_SESSION['$key']=$value;
            }
            mysql_close();

      Danke für eine Bestätigung oder Korrektur!
      Gruß -
      Sebastian

      PS:

      btw2: benutzereingaben ungeprüft in eine query zu übernehmen, wie due es anscheinend derzeit machst,

      Ich habe hier nur einen Ausschnitt genommen, den ich dann leicht modifiziert habe. Dabei fiel mir halt spontan ein $_POST['passwort'] ein - was der Realität selbstverfreilich nicht entspricht...

      1. hi,

        Also ungefähr so?:
              foreach((mysql_fetch_array($suche_result)) as $key => $value) {

        das fetchen würde ich ggf. vor der schleife machen. aber in diesem falle glaube ich schlicht geschmacksache, sollte auch so funktionieren.

        $_SESSION['$key']=$value;

        so aber nur, wenn du _alle_ werte in dem einen array-element mit dem index '$key' unterbringen willst.
        lies bitte zum einen im handbuch nach, wo die unterschiede bei der verwendung von anführungszeichen vs. hochkomata bei strings liegen - und gewöhne dir dann zum anderen bitte schleunigst ab, einfache variablen vollkommen unnötiger weise in eben solche zu verpacken.

        $_SESSION[$key] = $value; reicht hier vollkommen aus.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
      2. Moin!

        Warum nicht die einfache Methode?

        Also ungefähr so?:

          
        
        >       $suche_SQL="SELECT * FROM beispiel_tabelle WHERE benutzer='$benutzer'";  
          
        $suche_SQL="SELECT feld1, feld2, feld3 FROM tabelle WHERE benutzer = '".mysql_escape($benutzer)."' LIMIT 1'";  
          
        
        >       $suche_result=mysql_query($suche_SQL) OR die (mysql_error());  
          
        $_SESSION['benutzer'] = mysql_fetch_assoc($suche_result);  
          
        
        >       mysql_close();  
          
        
        

        Die Daten stehen dann in $_SESSION['benutzer']['feld1'] ff. drin - IMO eine sehr einfache Methode, das Zeug verfügbar zu machen.

        Es fehlt natürlich noch ein wenig Fehlerbehandlung - kann ja immerhin sein, dass aus der Datenbank nichts zurückkommt, dann würde in $_SESSION['benutzer'] ein "false" stehen. Der potentiellen Möglichkeit, dass zwei identische Benutzernamen existieren, setzt man am Besten einen Unique-Index auf die Benutzerspalte entgegen. Dann wäre eigentlich auch das "LIMIT 1" wieder entbehrlich... :)

        - Sven Rautenberg

        --
        My sssignature, my preciousssss!
        1. Hallo Sven,

            
          
          > $suche_SQL="SELECT feld1, feld2, feld3 FROM tabelle WHERE benutzer = '".mysql_escape($benutzer)."' LIMIT 1'";  
          > $_SESSION['benutzer'] = mysql_fetch_assoc($suche_result);  
          > mysql_close();  
          > Die Daten stehen dann in $_SESSION['benutzer']['feld1'] ff. drin - IMO eine sehr einfache Methode, das Zeug verfügbar zu machen.  
          
          

          Das sieht ja hervorragend einfach aus! Aber was genau meinst du mit $_SESSION['benutzer']['feld1']? Da ich nicht so der php-Held bin, verstehe ich das nicht so ganz. Wie greife ich auf die versch. Werte zu?
          Ich hätte mit meiner Methode gehofft, jeden einzelnen Wert als $_SESSION['feld1'] etc. ansprechen zu können. hat aber leider nicht funktioniert.
          Wieso muss ich bei deiner Methode nochmals den ['benutzer'] dazwischen hängen?

          Der potentiellen Möglichkeit, dass zwei identische Benutzernamen existieren, setzt man am Besten einen Unique-Index auf die Benutzerspalte entgegen.

          Hatte ich schon.

          Dann wäre eigentlich auch das "LIMIT 1" wieder entbehrlich... :)

          Stimmt :-)

          Gruß und Dank -
          Sebastian

          1. Moin!

            $suche_SQL="SELECT feld1, feld2, feld3 FROM tabelle WHERE benutzer = '".mysql_escape($benutzer)."' LIMIT 1'";
            $_SESSION['benutzer'] = mysql_fetch_assoc($suche_result);
            mysql_close();
            Die Daten stehen dann in $_SESSION['benutzer']['feld1'] ff. drin - IMO eine sehr einfache Methode, das Zeug verfügbar zu machen.

            
            > Das sieht ja hervorragend einfach aus! Aber was genau meinst du mit $\_SESSION['benutzer']['feld1']? Da ich nicht so der php-Held bin, verstehe ich das nicht so ganz. Wie greife ich auf die versch. Werte zu?  
              
            Zunächst mal hast du hoffentlich gesehen, dass ich dein "SELECT \*" durch eine Aufzählung aller abzufragenden Felder ersetzt habe. Mit dem Stern alle existierenden Spalten abzufragen sollte man nur zum Debugging testweise einsetzen, denn ein vernünftiges Datenbankdesign setzt voraus, dass dein Programm alle Datenbankfelder kennt, die es benutzen kann. Das macht beim Schreiben der SELECT-Querys zwar etwas mehr Aufwand, ist aber deutlich sauberer - denn andere als die aufgezählten Felder mit den entsprechenden Namen können dann nicht unerwartet im Ergebnis auftauchen.  
              
            
            > Ich hätte mit meiner Methode gehofft, jeden einzelnen Wert als $\_SESSION['feld1'] etc. ansprechen zu können. hat aber leider nicht funktioniert.  
            > Wieso muss ich bei deiner Methode nochmals den ['benutzer'] dazwischen hängen?  
              
            Ich gehe eigentlich immer davon aus, dass man im Session-Array mehrere Dinge speichern will, die thematisch nicht unbedingt etwas miteinander zu tun haben, und die sich auch nicht gegenseitig stören dürfen. Also beispielsweise einerseits deine Userdaten, andererseits einen Warenkorb. Oder das gewählte Seitendesign...  
              
            Du mußt nicht ['benutzer'] dazwischenhängen. Auch `$_SESSION=mysql_fetch_assoc()`{:.language-php} funktioniert - nur überschreibst du dir damit (und insbesondere wenn du SELECT \* benutzt) unter Umständen andere existierende Session-Werte, die unter dem gleichen Namen gespeichert wurden, wie deine DB-Spalten heißen.  
              
            Auch hier gilt: Meine vorgeschlagene Methode verursacht zwar jetzt tatsächlich mehr Tipparbeit, aber sie erleichtert es, später mal Erweiterungen vorzunehmen, die man recht leicht integrieren kann, ohne Konflikte befürchten zu müssen. Das ist einfach die Programmiererfahrung, die man mit der Zeit sammelt.  
              
             - Sven Rautenberg
            
            -- 
            My sssignature, my preciousssss!
            
  2. Hello,

    das ist schlecht.

    "Rechteabgleich mit Login" ist nämlich wesentlich unsicherer, als "Rechteabgleich im Momant des Bedarfes".

    Harzliche Grüße vom Berg
    esst mehr http://www.harte-harzer.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Hallo Tom!

      "Rechteabgleich mit Login" ist nämlich wesentlich unsicherer, als "Rechteabgleich im Momant des Bedarfes".

      Hä?

      Nichts verstanden habend -
      Sebastian

      1. Hello,

        "Rechteabgleich mit Login" ist nämlich wesentlich unsicherer, als "Rechteabgleich im Momant des Bedarfes".

        Hä?

        Nichts verstanden habend -

        Was hast Du denn daran nicht verstanden. 'hä?' ist mir wtwas zu dürftig.

        Du bewegst Dich soch in einer Multiuser-, Multisession-, Multithreading-, Umgebung. Da passieren viele Dinge überlappend oder gar "gleichzeitig".

        Wenn sich also ein User authentifiziert, und du dessen Rechte (usw) im Zeitpunkt des "Logins" (Besser: Identifikation) bereits als Snapshot konserviert hast, dann ändern sich diese Rchte über seine gesamte Session nicht mehr, auch wenn sie 10 Tage dauert und Du den User inzwischen gerne loswerden wolltest.

        Besser ist es daher, die Rechte _jedes_ Mal aus den aktuellsten Datenquellen zu holen, die es gibt.

        Harzliche Grüße vom Berg
        esst mehr http://www.harte-harzer.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. tach auch,

          Wenn sich also ein User authentifiziert, und du dessen Rechte (usw) im Zeitpunkt des "Logins" (Besser: Identifikation) bereits als Snapshot konserviert hast, dann ändern sich diese Rchte über seine gesamte Session nicht mehr, auch wenn sie 10 Tage dauert und Du den User inzwischen gerne loswerden wolltest.

          Ich konserviere nicht irgendwelche Rechte (denn er hat keine, weil es keine gibt), sondern lediglich seine Benutzerdaten. Name, E-Mail-Adresse und dergl.

          Bei rechten gebe ich dir allerdings recht - da wäre eine jeweilig aktuelle Abfrage sinnvoll.

          Gruß -
          Sebastian

          1. Hello,

            Bei rechten gebe ich dir allerdings recht - da wäre eine jeweilig aktuelle Abfrage sinnvoll.

            Beim Loginnamen und beim Passwort auch ;-)

            Harzliche Grüße vom Berg
            esst mehr http://www.harte-harzer.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
            1. Moin!

              Bei rechten gebe ich dir allerdings recht - da wäre eine jeweilig aktuelle Abfrage sinnvoll.

              Beim Loginnamen und beim Passwort auch ;-)

              Warum dieses? Das wird sich doch nicht ändern, da es ja eine Information ist, die der User gegeben hat, und die nicht vom Betreiber innerhalb der Session geändert werden kann. Der Username sowieso schon mal gar nicht, und das Passwort ist ebenfalls kein Datum, welches zu ändern in den Aufgabenbereich des Admins fällt. Will man den User wirklich loswerden, entzieht man ihm komplett die Rechte, und er fliegt dadurch aus den sensitiven Bereichen raus.

              Aber "Session-ID == Username+Passwort" - der Client übermittelt beim Login einmalig die Credentials, und nachfolgend nur noch die Session-ID, der Server speichert zu der ID die Credentials und gleicht die immer aktuell mit den erforderlichen Rechten ab.

              Usernamen und Passwort immer aktuell abzufragen wäre dann doch etwas lästig - bei jedem Seitenaufruf diese Daten neu anzugeben... bäh, so kann doch niemand arbeiten.

              - Sven Rautenberg

              --
              My sssignature, my preciousssss!
              1. Hello,

                Usernamen und Passwort immer aktuell abzufragen wäre dann doch etwas lästig - bei jedem Seitenaufruf diese Daten neu anzugeben... bäh, so kann doch niemand arbeiten.

                Wesentlich sollte nur sein, dass der User bei Änderung seines Passwortes nicht gezwungen ist, sich neu anzumelden, sondern dieses dann auch übernommen wird.

                Und warum sollte der Loginname nicht geändert werden können. In vernünftigen Systemen wird der sowieso genauso behandelt, wie ein Passwort, also auch verschlüsselt gespeichert und beim Frontend bei der Eingabe nicht im Klartext angezeigt. Im Backend sollte dann nicht mehr mit dem Namen sondern mit der UID gearbeitet werden und DIE sollte sich nach Vergabe tatsächlich nicht mehr ändern.

                Harzliche Grüße vom Berg
                esst mehr http://www.harte-harzer.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau
                1. Moin!

                  Usernamen und Passwort immer aktuell abzufragen wäre dann doch etwas lästig - bei jedem Seitenaufruf diese Daten neu anzugeben... bäh, so kann doch niemand arbeiten.

                  Wesentlich sollte nur sein, dass der User bei Änderung seines Passwortes nicht gezwungen ist, sich neu anzumelden, sondern dieses dann auch übernommen wird.

                  Dieses Bedien-Detail wäre mir primär ziemlich unwichtig. Manche Mechanismen wie beispielsweise HTTP-Auth lassen sich sogar garnicht so konfigurieren.

                  Und warum sollte der Loginname nicht geändert werden können. In vernünftigen Systemen wird der sowieso genauso behandelt, wie ein Passwort, also auch verschlüsselt gespeichert und beim Frontend bei der Eingabe nicht im Klartext angezeigt. Im Backend sollte dann nicht mehr mit dem Namen sondern mit der UID gearbeitet werden und DIE sollte sich nach Vergabe tatsächlich nicht mehr ändern.

                  Ein Loginname erfüllt alle Anforderungen an eine ID: Er ist zwingend unique und identifiziert eindeutig den Benutzer. Und er wird oftmals ohnehin nach mehr oder weniger eindeutig durchschaubaren Regeln gebildet, so dass eine Geheimhaltung und Verschlüsselung erstens sinnlos ist und zweitens die Administration behindert.

                  Oder wie willst du den Account des Loginnamens "beispieluser" sperren, wenn in der User-DB nur numerische IDs stehen, und als Loginname nur was verschlüsseltes?

                  Abgesehen davon: Könnte man den Benutzernamen ändern, ließe dich dadurch ja herausfinden, welche anderen Benutzernamen auch noch existieren (weil sie eben unique sein müssen), ohne gleichzeitig noch ein Passwort herausfinden zu müssen.

                  Das klingt alles noch nicht so wirklich überzeugend pro deines Standpunktes, muß ich sagen. :)

                  - Sven Rautenberg

                  --
                  My sssignature, my preciousssss!
                  1. Hello,

                    Oder wie willst du den Account des Loginnamens "beispieluser" sperren, wenn in der User-DB nur numerische IDs stehen, und als Loginname nur was verschlüsseltes?

                    Na, alle Geheimnisse verrate ich ja hier auch nicht. Ich muss doch noch was Dubioses zum Verkaufen durch die Hintertür behalten *gg*

                    Harzliche Grüße vom Berg
                    esst mehr http://www.harte-harzer.de

                    Tom

                    --
                    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                    Nur selber lernen macht schlau
        2. Hallo Tom,

          Besser ist es daher, die Rechte _jedes_ Mal aus den aktuellsten Datenquellen zu holen, die es gibt.

          Das mag in manchen Fällen richtig sein - verallgemeinern würde ich das aber nicht. In einer von mir geschriebenen Anwendung werden die Rechte einmal pro Session eingelesen - beim Einlogen. Da sich die Rechte sehr selten ändern (meist nur bei einem Update) ist es nicht wirklich sinnvoll bei jedem Request einen Query an die Datenbank abzufeuern (und falls es - wider Erwarten - doch mal nötig sein sollte, gibt es einen Menüpunkt "Rechte einlesen" der die Rechte neu ausliest). Und ja, es ist auch (ziemlich) ausgeschlossen, dass eine Session 10 Tage läuft: nach 30min wird der User zwangs-ausgelogt.

          Grüße aus Nürnberg
          Tobias

          1. Hello,

            Und ja, es ist auch (ziemlich) ausgeschlossen, dass eine Session 10 Tage läuft: nach 30min wird der User zwangs-ausgelogt.

            Programmierung ist immer Philosophie.
            Allerdings sollt man nicht an den falschen Stellen zu schraiben anfangen.

            Bezüglich Rechtestrukturen, konkurrierendem Betrieb und ihrer Praktikabilität binnich seit ca. 1984 ziemlich von NOVELL und Co geprägt. Ich orientiere mich sowohl an den guten Features, als auch (zur Vermeidung) an den Fehlern, die sie gemacht haben.

            Da ich recht früh mit PC-Client-Server (bTrieve nebst Extensions) angafangen habe, habe ich einige Irrwege und/oder Highlights mitgemacht...

            Die Entwicklung im Webbereich verfolgt die gleichen Pfade.

            Harzliche Grüße vom Berg
            esst mehr http://www.harte-harzer.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
          2. Moin!

            Und ja, es ist auch (ziemlich) ausgeschlossen, dass eine Session 10 Tage läuft: nach 30min wird der User zwangs-ausgelogt.

            Das bedeutet, egal ob der User neue Seiten anfordert oder nicht, dass er nach 30 Minuten immer wieder sein Passwort eingeben muß?

            Andernfalls ist es nämlich kein Problem, durch regelmäßige Aktionen (und sei es nur ein Reload der aktuellen Seite) die Session aktiv zu halten.

            - Sven Rautenberg

            --
            My sssignature, my preciousssss!
            1. Hallo Sven,

              Das bedeutet, egal ob der User neue Seiten anfordert oder nicht, dass er nach 30 Minuten immer wieder sein Passwort eingeben muß?

              nein, da habe ich mich undeutlich ausgedrückt - nach 30min _Inaktivität_ wird der User zwangs-ausgelogt.

              Andernfalls ist es nämlich kein Problem, durch regelmäßige Aktionen (und sei es nur ein Reload der aktuellen Seite) die Session aktiv zu halten.

              wer lässt schon seinen Rechner z.B. die ganze Nacht durchlaufen um eine bestimmte Seite regelmäßig neuladen zu lassen? Das halte ich (vor allem bei meiner Seite) doch für _sehr_ unwahrscheinlich :-)

              Grüße aus Nürnberg
              Tobias

              1. Moin!

                Das bedeutet, egal ob der User neue Seiten anfordert oder nicht, dass er nach 30 Minuten immer wieder sein Passwort eingeben muß?
                nein, da habe ich mich undeutlich ausgedrückt - nach 30min _Inaktivität_ wird der User zwangs-ausgelogt.

                Das ist normal. Löst dann aber die angesprochene Problematik nicht.

                Andernfalls ist es nämlich kein Problem, durch regelmäßige Aktionen (und sei es nur ein Reload der aktuellen Seite) die Session aktiv zu halten.
                wer lässt schon seinen Rechner z.B. die ganze Nacht durchlaufen um eine bestimmte Seite regelmäßig neuladen zu lassen? Das halte ich (vor allem bei meiner Seite) doch für _sehr_ unwahrscheinlich :-)

                Würdest du aber widersprechen, wenn ich als Beispiel für eine sinnvolle Anwendung ein Online-Bankkonto heranziehe: Jemand hat durch eine Phishing-Mail seine Zugangsdaten weitergegeben, das aber gemerkt und der Bank gemeldet - aber nicht schnell genug, der Betrüger hat sich bereits eingeloggt. Wenn es jetzt keine Möglichkeit gibt, den Bösewicht durch Kontosperrung aus dem Login rauszuwerfen, wäre das ein ziemliches Armutszeugnis.

                - Sven Rautenberg

                --
                My sssignature, my preciousssss!
                1. Hallo Sven,

                  Würdest du aber widersprechen, wenn ich als Beispiel für eine sinnvolle Anwendung ein Online-Bankkonto heranziehe: Jemand hat durch eine Phishing-Mail seine Zugangsdaten weitergegeben, das aber gemerkt und der Bank gemeldet - aber nicht schnell genug, der Betrüger hat sich bereits eingeloggt. Wenn es jetzt keine Möglichkeit gibt, den Bösewicht durch Kontosperrung aus dem Login rauszuwerfen, wäre das ein ziemliches Armutszeugnis.

                  natürlich - nur meine Anwendung ist lediglich eine Mitgliederverwaltung für eine Abteilung eines Sportverein - da braucht man sowas imho nicht (auch wenn ich trotzdem noch was einbauen will, um für Updates o.ä. alle angemeldeten User rauswerfen zu können).

                  Grüße aus Nürnberg
                  Tobias