Nick: Session / Mysql

Hi,

ich versuche mich grad ein bisschen an Perl mit Mysql und würde gerne eine Userverwaltung machen, sprich man kann sich auf der website anmelden und dann in seinem Bereich irgenwas machen - z.B. sein geburtstag eintragen oder sowas.
Meine Frage ist nun, wie macht man das am besten mit der session-verwaltung?
Also sobald sich der User ja angemeldet hat ruft er irgendwelche formulare auf hinter denen ein perl-script steckt, das daten in der DB verändert. Wie kann ich nun am besten sicherstellen das ich die Daten des angemeldeten users verwende, ohne das er jedesmal wieder user/pw eingeben muss?
Soll ich dann die user/pw in ein cookie schreiben und das auslesen?
Wie macht man das am besten? Wie macht ihr das?
Danke für Tipps/links/sonstige Hilfe.

ciao,
nick

  1. hi,

    ich mache das so:
    User gibt seine Credentials (Benutzername, Passwort) ein und authentifiziert sich. Wenn Ok, wird eine Session aufgebaut. Dazu wird serverseitig ein eindeutiger (1) Key generiert, der einmal auf dem Server gespeichert und zum Anderen in einem Cookie an den Client geschickt wird.

    Der Cookie ist nur solange gültig, wie die Browsersitzung besteht. Die Session ist solange gültig, wie der Session-Key im Cookie, der bei jedem Request mitgeschickt wird, gleichermaßen auf dem Server, bspw. in einer Datenbank vorhanden ist.

    (1) Es darf innerhalb einer sehr, sehr großen Menge von möglichen Sessions KEINE Duplikate geben. Um einen solchen Key zu erzeugen, nehme ich die PID (Prozess-ID), das Datum, eine Zufallszahl und encrypte das mit Digest::MD5 oder mit der Perl-Funktion crypt(); und einem zufälligen Salt.

    Die Dauer einer Session beschränke ich auch auf max 24 Stunden. Ein Cronjob fegt alle Session-Records von der Tabelle, die älter sind.

    Neben einer Authentifizierung (Anmeldung mit Name, Password), kann die Anwendung weitere Dinge festlegen, wofür bestimmte User Authoriziert sind. Ich schreibe das deswegen mal hier auf, damit beide Begriffe, die oft miteinander verwechselt werden, einmal zweckmäßg in ein und demselben Textabschnitt stehen.

    Auf jeden Fall ist es schlecht, einen Session-Key in der URL zu encoden, damit lassen sich Sessions sehr einfach auf Dritte übertragen, was mit einem cookie nicht so ohne Weiteres möglich ist.

    Viele Grüße,
    Horst Haselhuhn

    1. hi,

      ich mache das so:
      User gibt seine Credentials (Benutzername, Passwort) ein und authentifiziert sich. Wenn Ok, wird eine Session aufgebaut. Dazu wird serverseitig ein eindeutiger (1) Key generiert, der einmal auf dem Server gespeichert und zum Anderen in einem Cookie an den Client geschickt wird.

      Hi,

      dann hast du wahrscheinlich bei jedem deiner Scripte am Anfang eine Abfrage ob der Key im Cookie (via POST übertragen schätze ich) irgendwo in deiner DB verknüpft mit einer UID i.O. ist?!
      Ich überleg mir ob ich "nur" die uid und das mit crypt verschlüsselte passwort in das cookie speichern soll. Ich weiss, dass man mit dem salt und dem tool crack es je nach schwierigkeitsgrad leicht rel. leicht entschlüsseln kann, aber so brauch ich keinen session-key in der DB.

      Danke für die Tipps.

      ciao,
      nick

      1. hi,

        dann hast du wahrscheinlich bei jedem deiner Scripte am Anfang eine Abfrage ob der Key im Cookie (via POST übertragen schätze ich) irgendwo in deiner DB verknüpft mit einer UID i.O. ist?!

        die Request-Method GET oder POST spielt bei meinen Sessions absolut keine Rolle.

        Die Abfrage ob die Session gültig ist, beschränkt sich lediglich darauf, ob der Key Clientseitig == Serverseitig vorhanden ist.

        Hier eine Perl-Funktion, die einen sehr eindeutigen Key erzeugt:

        sessionid generieren

        sub initid{
         # salts erzeugen
         my @salts = ("a".."z");
         shuffle(@salts);
         my $salt = join "", @salts;

        # und nun crypten
         my $zufall = crypt($salt,time.$$);
         return $zufall;
        }

        -- Hotte

        1. Moin Moin!

          Hier eine Perl-Funktion, die einen sehr eindeutigen Key erzeugt:

          Aber nicht notwendigerweise einen guten Key.

          sessionid generieren

          sub initid{

          salts erzeugen

          my @salts = ("a".."z");
          shuffle(@salts);

          shuffle ist kein Buildin. Woher kommt diese Funktion?

          my $salt = join "", @salts;

          und nun crypten

          my $zufall = crypt($salt,time.$$);

          Crypt nutzt die ersten zwei Zeichen von salt. Das ergibt 26*26=676 mögliche Kombinationen. time() ist per HTTP sekundengenau zu ermitteln. $$ (PID) ist mehr oder weniger monoton steigend, bis ein Wrap-Around bei 2^15 oder 2^16 erfolgt. $$ wird auf Unix-Systemen nie 0 und nie 1 sein, und auf typischen Systemen auch eher selten eine Zahl unter 20 (Kernel-Prozesse belegen die ersten paar PIDs).

          Ich würde mal sagen, das sollte recht einfach von einem externen Rechner vorberechenbar sein.

          Ein typischer Anfängerfehler ist, selbst einen Zufallsgenerator zu schrieben. Leider sind die selten zufällig.

          Der folgende Code aus einem meiner Projekte erzeugt eine ID, die nur von Perls Pseudozufallsgenerator abhängig ist:

            
          my @idchars=('A'..'Z','a'..'z','0'..'9');  
          my $idcharCount=@idchars;  
          my $idlen=72;  
            
          sub newID # => $id  
          {  
              my $id='';  
              $id.=$idchars[int rand $idcharCount] for 1..$idlen;  
              return $id;  
          }  
          
          

          Richtig gut wird die ID, wenn man sich aus einem harten Zufallsgenerator (minimal /dev/random unter Linux) eine Hand voll Bytes holt und diese "nackt" oder Base64-codiert verwendet.

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. Ok, ok, Ok,

            lieber Alexander,

            mein Code ist ne Weile her, ich finde den selbst durchaus sehr verbesserungswürdig.

            So wie ich das heute sehe.

            Und Ja: Mein richtiges Know How. Das Poste ich hier schon lange nicht mehr. Ich bin hier oft genug in den Arsch getreten worden. Auch von Angehörigen des SELF-Vereins.

            Wie auch immer: Ich schreibe so, das ein Entwickler damit was anfangen kann.

            Viele Grüße,
            Rolf

          2. Der folgende Code aus einem meiner Projekte erzeugt eine ID, die nur von Perls Pseudozufallsgenerator abhängig ist:

            Da gibt's auch was im Archiv:
            http://forum.de.selfhtml.org/archiv/2005/1/t98234/#m598642

            (Der Vollständigkeit halber)

            Siechfred

            --
            Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
      2. Moin Moin!

        dann hast du wahrscheinlich bei jedem deiner Scripte am Anfang eine Abfrage ob der Key im Cookie (via POST übertragen schätze ich) irgendwo in deiner DB verknüpft mit einer UID i.O. ist?!

        In Pseudo-SQL:

        0. create table sessions ( id varchar(100) not null primary key, user_id int not null, expire_date timestamp not null, .... )

        1. delete from sessions where expire_date<now()
        2. select user_id from sessions where id=?
        Falls kein Ergebnis: redirect zum Login-Formular. Falls eine Zeile: Angemeldet, weitermachen. Mehr als eine Zeile: Panik.
        3. update sessions set expire_date=now()+30 minutes where id=?

        Dann dispatch auf die gewünschte Funktion. Falls Du Session-Daten brauchst, ändere Schritt 2 in ein nicht zählendes SELECT und überprüfe, wie viele Zeilen Dir DBI liefert. 0 => login, 1 => arbeiten, sonst => Panik.

        Nach erfolgreichem Login:

        Session-ID auswürfeln (NIEMALS ein vorhersagbare ID benutzen, also nicht zählen, nicht die Uhrzeit oder Prozess-ID benutzen). 20 bis 100 Buchstaben und Zahlen geben eine brauchbare Session-ID ab.

        So ca. 20 mal insert into sessions (id,user_id,expire_date,...) values (?,?,now()+30 minutes,...) ausprobieren, bis es nicht mehr fehlschlägt, dabei in jeder Runde eine neue Session-ID benutzen. Nach 20 Fehlversuchen Panik.

        Cookie mit der Session-ID setzen und auf die ursprünglich angeforderte Seite weiterleiten.

        Ich überleg mir ob ich "nur" die uid und das mit crypt verschlüsselte passwort in das cookie speichern soll. Ich weiss, dass man mit dem salt und dem tool crack es je nach schwierigkeitsgrad leicht rel. leicht entschlüsseln kann, aber so brauch ich keinen session-key in der DB.

        Ganz blöde Idee. Die DB-Abfrage brauchst Du immer, egal ob Du einen User aus der DB fischst oder einen User und eine Session. Das macht keinen Unterschied, es sei denn, Deine DB ist über einen Akustikkoppler an den Webserver angebunden. Wenn jemand den Cookie mit UID+Password und irgendeiner Verschlüsselung abgreifen kann, kommt er IMMER in das System. Die Session dagegen läuft nach kurzer Zeit ab, es ist nicht einmal nötig, zum Abmelden den Cookie zu löschen, ein simples "delete from sessions where id=?" reicht vollkommen aus.

        Du kannst Dir übrigens einen Großteil der Arbeit sparen, auf CPAN gibt es jede Menge Module für die Session-Verwaltung.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".