kEv*: nach Login gültigen Account prüfen

Hallo liebe SELFHTMLer,

ich habe das Loginscript welches hier unter SELFHTML angeboten wird an meine
Anwendung etwas angepasst und stehe nun etwas auf dem Schlauch.

Vorerst der Code:

  
...  
  
$sql = mysql_query("SELECT * FROM user WHERE username = '".mysql_real_escape_string($_POST['username'])."' AND password = '".md5(mysql_real_escape_string($_POST['password']))."' ");  
 $res = mysql_num_rows($sql);  
 if ($res == 1){  
  $data = mysql_fetch_object($sql);  
     # Benutzerinformationen in der Session speichern  
  $_SESSION['loggedin'] = true;  
  $_SESSION['uid'] = $data->uid;  
  $_SESSION['username'] = $data->username;  
  $_SESSION['levelid'] = $data->levelid;  
  $_SESSION['sessionid'] = session_id();  
  $now = date('Y-m-d H:i:s', time());  
  
  # Abfragen auf gültigen Account  
  $sql = mysql_query("SELECT expire, accountstatus FROM user WHERE uid = '" . $_SESSION['uid'] . "' LIMIT 1");  
  $res = mysql_fetch_object($sql);  
  
  if ($res->expire > $now){  
   $error = true;  
   $errormsg = "Dein Account ist abgelaufen!";  
  }  
  elseif($res->accountstatus == 1){  
   $error = true;  
   $errormsg = "Dein Account ist nicht freigeschaltet!";  
  }  
  elseif($res->accountstatus == 2){  
   $error = true;  
   $errormsg = "Dein Account ist gesperrt!";  
  }  
  
  
  # div. Daten in user Tabelle aktualisieren  
  mysql_query('UPDATE user SET sessionid = "' . session_id() . '", lastlogin = NOW() WHERE uid = "' . $_SESSION['uid'] . '" LIMIT 1');  
  
  # Server Protocol prüfen  
  if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1'){  
   if (php_sapi_name() == 'cgi'){  
    header('Status: 303 See Other');  
    }  
   else{  
    header('HTTP/1.1 303 See Other');  
   }  
  }  
  #Weiterleitung zum internen Bereich  
  header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/index.php?sid='.$_SESSION['sessionid']);  
  disconnect();  
  exit;  
 }  
 # fehlerhafter Login  
 # ggf. Errorhandling  
 else{  
  $error = true;  
  $errormsg = "Benutzername und/oder Passwort fehlerhaft!";  
 }  

Mein derzeitiges Problem liegt in der if elseif Abfrage. Ich möchte gern nach erfolgreichem Login noch prüfen ob von dem User der Account gesperrt ODER nicht freigegeben ODER abgelaufen ist und ggf. eine Meldung dazu ausgeben. Natürlich soll sich der User nicht einloggen können wenn eine der 3 Bedingungen erfüllt ist und wieder auf der Login.php landen. mit eben entsprechender Meldung.

Mit einem exit; wird das Script verlassen aber die Seite bleibt leider weiß.

Warum und wie könnte ich mein oben beschriebenes Problem lösen?

LG
kev1n

--

SELFCODE:
sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
---
  1. Hallo kev1n,

    Warum und wie könnte ich mein oben beschriebenes Problem lösen?

    Na im Prinzip so:

    if(Benutzername und Passwort OK)
     {
      Datenbankabfragen für weitere überprüfungen;
      if(Überprüfungen OK)
       {
        Session einrichten;
        Nach Userbereich weiterleiten;
       }
      else
       {
        zurück zum Login mit entsprechender Meldung;
       }
     }

    Ale×

    1. Hi,

      if(Benutzername und Passwort OK)
      {
        Datenbankabfragen für weitere überprüfungen;

      Das ist doch unnoetig, wenn's eh auf die gleiche Tabelle geht.

      Mit Benutzername und Passwort alle interessanten Spalten abfragen.
      Entweder gibt's kein Ergebnis, dann gibt's den Benutzer nicht, oder das Passwort stimmt nicht.
      Andernfalls erhaelt man einen Datensatz, aus dem man dann den Account-Status erfragen und ueberpruefen kann.

      MfG ChrisB

      --
      „This is the author's opinion, not necessarily that of Starbucks.“
      1. Hallo ChrisB,

        Das ist doch unnoetig, wenn's eh auf die gleiche Tabelle geht.

        Stimmt, in dem Fall ist's unnötig. Hab mir nicht so genau angeschaut, was da noch gemacht werden soll und aus welcher Tabelle die Daten dafür kommen.

        Ale×

        1. Hallo liebe SELFHTMLer,

          und aus welcher Tabelle die Daten dafür kommen.

          Die Daten kommen aus der gleichen Tabelle.
          So soll es aussehen.

          Prüfen auf Benutzer und Passwort
          OK - > Weiter
          Prüfen ob Account freigeben
          OK -Login fertig - Sessiondaten schreiben und Weiterleitung zur index.php

          ANDERENFALLS

          Account gesperrt
             MELDUNG
          ODER
          Account nicht freigeschaltet
             MELDUNG

          Keine Session starten. Abbruch.

          Verständlicher? Ich möchte gern die Fehler bzw. den Status der Abfrage nicht verallgemeinern und somit eine Meldung ausgeben.
          LG
          kev1n

          --

          SELFCODE:
          sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
          ---
          1. Hi kEv*!

            So soll es aussehen.

            Ja, aber wo ist dein Problem?

            Exit löst deine Probleme nicht. Damit brichst du das Script nur ab.

            Verständlicher? Ich möchte gern die Fehler bzw. den Status der Abfrage nicht verallgemeinern und somit eine Meldung ausgeben.

            Dann tu das doch. ;-)

            Zu deiner Fehlerbehandlung:
            Du musst ja zurück auf die Loginseite leiten und dort ggf. eine Fehlermeldung ausgeben. Sinnvoll ist es, jedem Fehler eine ID zu verpassen. Unter dieser ID ist der Fehler dann auffindbar.

            Möglich wäre z. B. folgendes:

            define('ERROR_INVALIDLOGIN',1);  
            define('ERROR_LOCKEDACCOUNT',2);  
            define('ERROR_3',4);  
            define('ERROR_4',8);  
            define('ERROR_FOO',16);  
            define('ERROR_BAR',32);  
            // Wichtig: Zweierpotenzen, die nicht doppelt vorkommen dürfen!  
            // Bei größeren Projekten mit mehr Fehlermeldungen  
            // kann es sinnvoll zu sein, auf fortlaufende IDs  
            // zurückzugreifen.  
            // Dann muss man natürlich anders auf den jeweiligen  
            // Fehler überprüfen.  
              
            $ERROR = array(  
                        ERROR_INVALIDLOGIN => array(  
                            'level' => 2,  
                            'msg' => 'Ungültiger Login [bla bla bla].'  
                        ),  
                        ERROR_LOCKEDACCOUNT => array(  
                            'level' => 1,  
                            'msg' => 'Account gesperrt [bla bla bla].'  
                        ) // ...  
                    );
            

            Bei einem Fehler setzt du einfach die Fehlerkonstante mit einer Sessionvariable:

            $_SESSION['error'] += ERROR_FOO;

            Auf deiner Loginseite musst du dann auf den Fehler überprüfen:

            // Fehler?  
            if($_SESSION['error'] & ERROR_BAR) {  
              // Fehler soundso  
              // Um auf einen Fehler zuzugreifen:  
              tuwas_mit($ERROR[ERROR_INVALIDLOGIN ]['level']);  
              // ...  
            }
            

            Ich hoffe, das hilft dir weiter.

            MfG H☼psel

            --
            "It's amazing I won. I was running against peace, prosperity, and incumbency."
            George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
            Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
            1. Hallo liebe SELFHTMLer,

              Danke H☼psel.
              Dein Hinweis war die gesuchte Lösung.

              login.php

                
              <?php  
              if ($_SERVER['REQUEST_METHOD'] == 'POST'){  
               session_start();  
               $_SESSION['error'] = "";  
               $hostname = $_SERVER['HTTP_HOST'];  
               $path = dirname($_SERVER['PHP_SELF']);  
                
               # php includieren  
               include('constanten.inc.php');  
               include('functions.inc.php');  
               connect();  
                
               # auf Benutzername UND Passwort prüfen  
               # mysql_real_escape_string() zum verhindern von SQL - Injections  
               $sql = mysql_query("SELECT * FROM user WHERE username = '".mysql_real_escape_string($_POST['username'])."' AND password = '".md5(mysql_real_escape_string($_POST['password']))."' ");  
               $res = mysql_num_rows($sql);  
               if ($res == 1){  
                
                $data = mysql_fetch_object($sql);  
                # Accountcheck  
                if ($data->expire < DateTime){  
                 $_SESSION['error'] = ACCOUNTEXPIRED;  
                }  
                elseif($data->accountstatus == 1){  
                 $_SESSION['error'] = ACCOUNTNOTENABLED;  
                }  
                elseif($data->accountstatus == 2){  
                 $_SESSION['error'] = ACCOUNTLOCKED;  
                }  
                
                # Server Protocol prüfen  
                if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1'){  
                 if (php_sapi_name() == 'cgi'){  
                  header('Status: 303 See Other');  
                  }  
                 else{  
                  header('HTTP/1.1 303 See Other');  
                 }  
                }  
                # Weiterleitung zum internen Bereich  
                if (!$_SESSION['error']){  
                 # Benutzerinformationen in den Sessionvariablen speichern  
                 $_SESSION['loggedin'] = true;  
                 $_SESSION['uid'] = $data->uid;  
                 $_SESSION['username'] = $data->username;  
                 $_SESSION['levelid'] = $data->levelid;  
                 $_SESSION['sessionid'] = session_id();  
                
                 # user Tabelle aktualisieren  
                 mysql_query('UPDATE user SET sessionid = "' . session_id() . '", lastlogin = NOW() WHERE uid = "' . $_SESSION['uid'] . '" LIMIT 1');  
                
                 header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/index.php?sid='.$_SESSION['sessionid']);  
                 disconnect();  
                 exit;  
                }  
               }  
               # fehlerhafter Login  
               # ggf. Errorhandling  
               else{  
                $_SESSION['error'] = INVALIDLOGIN;  
               }  
              }  
              ?>  
                
              hier kommt DOCTYPE und Co.  
              ...  
                
                  <?php  
               if (isset($_SESSION['error']) && $_SESSION['error']){  
               ?>  
                  <tr>  
                   <td colspan="2" class="error"><?php echo $_SESSION['error']; ?></td>  
                  </tr>  
                  <?php  
               }  
               ?>  
              ...  
                
              
              

              constanten.inc.php

                
              <?php  
              define('DateTime',date('Y-m-d H:i:s', time()));  
                
                
              # Fehlermeldungen  
              define('INVALIDLOGIN','Benutzername und/oder Passwort fehlerhaft!');  
              define('ACCOUNTLOCKED','Ihr Account ist gesperrt!');  
              define('ACCOUNTNOTENABLED','Ihr Account ist nicht freigeschaltet!');  
              define('ACCOUNTEXPIRED','Ihr Account ist abgelaufen!');  
              ?>  
              
              

              logout und auth.php sind nur gering geändert zu dem LoginScript hier auf SELFHTML.

              Was kann ich besser machen, oder ggfs. sicherer?
              Soweit funktioniert das Login und ich bin zufrieden.

              Danke nochmal an alle Beteiligten für die Hilfe.
              LG
              kev1n

              --

              SELFCODE:
              sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
              ---
              1. Hi kEv*!

                Was kann ich besser machen, oder ggfs. sicherer?

                Ich finde, das ist soweit ganz okay.

                Nur ein paar Verbesserungswürdige Punkte:
                1. Wenn du statt mysql_fetch_object mysql_fetch_assoc nutzt und
                2. im SQL-Statement eine explizite Projektion hast (also kein *), dann kannst du
                3. deine Sessionvariablen mir foreach($data as $key=>$value) zusammenstellen. Wenn sich an den benötigten Daten mal was ändert, brauchst du nur das SELECT-Statement ändern.

                4. Deine Fehlerbehandlung erlaubt dir nicht, mehrere Fehler zu behandeln. Das könnte evtl. später von Nachteil sein. Auch eine Gewichtung bekommst du so nicht. Es ist ein Unterschied, ob ich meinen Benutzernamen oder mein Passwort falsch eingegeben habe oder ob mein Account gesperrt ist. Mit hübschen Icons und entsprechenden CSS-Klassen kannst du solche Fehlermeldungen etwas aufbohren.

                5. ein mit md5 verschlüsseltes Passwort solltest du vorher nicht mit mysql_real_escape_string() behandeln. Es kann vorkommen, dass du dann einen anderen Hash in die Datenbank speicherst, als den vom Originalpasswort generierten Hash.

                6. Wenn du ein neues Projekt planst, solltest du kein Tabellendesign mehr nutzen. Es wird die viel Arbeit ersparen.

                7. Vergleiche in deiner if-Abfrage if (isset($_SESSION['error']) && $_SESSION['error']) besser auf die Länge des Strings. Ich weiß nicht, wie sich der Compiler verhält, wenn z. B. eine 0 am Anfang des String stehen würde.

                Das sind alles nur Vorschläge, die dir aber für künftige Projekte vielleicht helfen.

                MfG H☼psel

                --
                "It's amazing I won. I was running against peace, prosperity, and incumbency."
                George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
                Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
                1. Hallo liebe SELFHTMLer,

                  Hi kEv*!

                  Was kann ich besser machen, oder ggfs. sicherer?
                  Ich finde, das ist soweit ganz okay.

                  Danke.

                  Nur ein paar Verbesserungswürdige Punkte:

                  1. Wenn du statt mysql_fetch_object mysql_fetch_assoc nutzt und
                  2. im SQL-Statement eine explizite Projektion hast (also kein *), dann kannst du
                  3. deine Sessionvariablen mir foreach($data as $key=>$value) zusammenstellen. Wenn sich an den benötigten Daten mal was ändert, brauchst du nur das SELECT-Statement ändern.

                  Werde ich umsetzen. Klingt vernüftig und irgendwie auch logisch. :)

                  1. Deine Fehlerbehandlung erlaubt dir nicht, mehrere Fehler zu behandeln. Das könnte evtl. später von Nachteil sein. Auch eine Gewichtung bekommst du so nicht. Es ist ein Unterschied, ob ich meinen Benutzernamen oder mein Passwort falsch eingegeben habe oder ob mein Account gesperrt ist. Mit hübschen Icons und entsprechenden CSS-Klassen kannst du solche Fehlermeldungen etwas aufbohren.

                  Ist so eigentlich auch nicht geplant. Es soll eingentlich ein Fehler nach dem anderen kommen. Wenn ich aber so darüber nachdenke, ist das nicht benutzerfreundlich.

                  1. ein mit md5 verschlüsseltes Passwort solltest du vorher nicht mit mysql_real_escape_string() behandeln. Es kann vorkommen, dass du dann einen anderen Hash in die Datenbank speicherst, als den vom Originalpasswort generierten Hash.

                  Ok, wird auch geändert.
                  Wenn ich das richtig verstanden habe ...
                  erst escapen und dann durch die md5 Funktion jagen?

                  1. Wenn du ein neues Projekt planst, solltest du kein Tabellendesign mehr nutzen. Es wird die viel Arbeit ersparen.

                  Ich will und werde mich bessern und auf CSS und semantisches html umstellen. Sofern mir das gelingt. :(

                  1. Vergleiche in deiner if-Abfrage if (isset($_SESSION['error']) && $_SESSION['error']) besser auf die Länge des Strings. Ich weiß nicht, wie sich der Compiler verhält, wenn z. B. eine 0 am Anfang des String stehen würde.

                  Ok. Wird ebenfalls umgesetzt. Ich programmiere noch nicht so lange php und mysql und bin für jeden Hinweis dankbar.

                  Das sind alles nur Vorschläge, die dir aber für künftige Projekte vielleicht helfen.

                  Vielen Dank nochmal.

                  LG
                  kev1n

                  --

                  SELFCODE:
                  sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
                  ---
                  1. echo $begrüßung;

                    1. ein mit md5 verschlüsseltes Passwort solltest du vorher nicht mit mysql_real_escape_string() behandeln. Es kann vorkommen, dass du dann einen anderen Hash in die Datenbank speicherst, als den vom Originalpasswort generierten Hash.
                      Wenn ich das richtig verstanden habe ...
                      erst escapen und dann durch die md5 Funktion jagen?

                    Nein, erst nachdenken, dann implementieren. Genau sorum hast du es ja jetzt schon. Wofür wird denn das Maskieren gemacht? Weil ein ' als Datenbestandteil in einem mit ' begrenzten String den String beendet und nachfolgende Daten nicht mehr als Daten angesehen werden. Es ist also der Kontext "String im SQL-Statement" zu beachten. Wenn du nun aus einem ' ein ' machst und von solch einem String den Hashwert berechnest, bekommst du einen anderen Wert als ohne . Der Kontext ist hier aber Hashwert errechnen und nicht "String im SQL-Statement", eine Maskierung fehl am Platz.

                    Ein md5()-Ergebnis ist garantiert ein String ohne kritische Zeichen. Es reicht also den Wert unbehandelt in das SQL-Statement einzufügen. Andererseits schadet es auch nicht, auf den MD5-Wert eine Maskierung anzuwenden.

                    echo "$verabschiedung $name";

                    1. Hallo liebe SELFHTMLer,

                      Nein, erst nachdenken, dann implementieren. Genau sorum hast du es ja jetzt schon. Wofür wird denn das Maskieren gemacht? Weil ein ' als Datenbestandteil in einem mit ' begrenzten String den String beendet und nachfolgende Daten nicht mehr als Daten angesehen werden. Es ist also der Kontext "String im SQL-Statement" zu beachten. Wenn du nun aus einem ' ein ' machst und von solch einem String den Hashwert berechnest, bekommst du einen anderen Wert als ohne . Der Kontext ist hier aber Hashwert errechnen und nicht "String im SQL-Statement", eine Maskierung fehl am Platz.

                      Das verstehe ich bis heute nicht richtig wann " oder ' oder nix. :(
                      Wo kann ich mich dazu besser belesen?
                      Ich probiere irgendwie immer solange bis das in der DB steht was rein soll.
                      Das ist gar nicht gut.

                      Ein md5()-Ergebnis ist garantiert ein String ohne kritische Zeichen. Es reicht also den Wert unbehandelt in das SQL-Statement einzufügen. Andererseits schadet es auch nicht, auf den MD5-Wert eine Maskierung anzuwenden.

                      Nochmals vielen Dank.
                      LG
                      kev1n

                      --

                      SELFCODE:
                      sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
                      ---
                      1. echo $begrüßung;

                        Das verstehe ich bis heute nicht richtig wann " oder ' oder nix. :(

                        Wenn zwei Kontexte zusammenkommen, muss man beide eindeutig unterscheiden können. Da ist das SQL-Statement, das (vereinfacht gesagt) Buchstaben und Leerzeichen nutzt, um eine Anweisung zu formulieren. Und da ist ein Wert, der in diese Anweisung eingefügt werden soll, der ebenfalls aus Buchstaben und Leerzeichen besteht. Wie kennzeichnet man nun diesen Wert so, dass er nicht mit dem Anweisungsteil verwechselt werden kann? Man beginnt und beendet ihn mit je einem Anführungszeichen. (Das nennt man Quotieren). Soweit so einfach. Jedoch sind auch Satzzeichen, wie ebenjenes Anführungszeichen mitunter Bestandteil der Daten und dann muss man es so notieren, dass der Statement-Interpreter es nicht als beendendes Anführungszeichen interpretiert. Dafür kommt das Maskieren ins Spiel. Das Anführungszeichen bekommt eine Maske vorgesetzt, so dass es nicht als solches erkannt wird. Wenn der Kontext »String im SQL-Statement« nicht vorliegt, muss auch nicht dafür maskiert werden. (Bei md5($wert) ist der Kontext »Funktionsaufruf«, für den nichts weiter zu beachten ist.)

                        Dass es nun sowohl " als auch ' gibt, ist dafür gedacht, sich teilweise die Maskierungen zu ersparen, wenn man mehrere Kontexte ineinanderschachtelt. Weiterhin haben in bestimmten Systemen die beiden Zeichen unterschiedliche Auswirkungen auf den Inhalt, was vor der Entscheidung für " oder ' zu beachten ist. PHP behandelt " und ' unterschiedlich, MySQL nicht.

                        $sql = "SELECT * FROM table WHERE feld='wert'";

                        In diesem Beispiel müssen die drei Kontexte PHP-String, SQL-Statement und SQL-String mit zwei Quotierzeichen auskommen. Das SQL-Statement verwendet das " nicht, weswegen es als PHP-Quotierzeichen verwendet werden kann. Auch andersrum geschachtelt ist eine Notation in diesem einfachen Beispiel möglich, da keine unter PHP besonders behandelten Dinge (z.B. Variablennamen) vorkommen.

                        $sql = 'SELECT * FROM table WHERE feld="wert"';

                        Problematisch wird die Sache erst, wenn »wert« variabel sein soll und Zeichen wie ' oder " enthalten können soll.

                        $sql = "SELECT * FROM table WHERE feld='$wert'";

                        Für den Kontext PHP-String brauchen wir den Inhalt von $wert nicht zu betrachten. Der Parser, der den Kontext PHP-String zu beachten hat, ist längst gelaufen, wenn es darum geht, den Inhalt von $wert in den String einzufügen. Aber der Kontext SQL-Statement und darin SQL-String ist noch zu beachten, den löst ja erst später das DBMS auf.

                        Wir haben nun den Kontext »mit ' eingefasster SQL-String«, und da hat ein " keine Bedeutung. Bleibt also noch, vorkommende ' zu entschärfen. Die Arbeit des Maskierens nimmt die Funktion mysql_real_escape_string() ab. Ihr Aufruf erfolgt ja auch erst zur Laufzeit, wenn der restliche Statement-String bereits geparst in den Tiefen des PHP-Systems vorliegt und den Kontext PHP-String hinter sich gelassen hat, so dass dieser hier ebenfalls nicht beachtet werden muss. Dass die Funktion neben ' auch " maskiert ist in diesem konkreten Fall überflüssig, aber nicht weiter tragisch. Sie muss ja auch für den Fall »mit " eingefasster SQL-String« arbeiten können.

                        Ergebnis ist der String

                        SELECT * FROM table WHERE feld='wert mit einem ' drin'

                        den du dir mit einer Kontrollausgabe ansehen kannst. Auch ein

                        SELECT * FROM table WHERE feld='wert mit einem ' und einem " drin'

                        wäre richtig, doch mysql_real_escape_string() erzeugt

                        SELECT * FROM table WHERE feld='wert mit einem ' und einem " drin'

                        was ja unproblematisch ist. Auch dann, wenn der SQL-String mit " eingerahmt wäre

                        SELECT * FROM table WHERE feld="wert mit einem ' und einem " drin"

                        denn der MySQL-Parser löst ' und " zu ' und " auf, egal wie der String eingefasst war.

                        Bleibt noch der Fall, wann »nix« zu verwenden ist. Eine Zahl ist eindeutig als solche zu erkennen. Sie beginnt mit einem der Zahl-Zeichen (Ziffern, Vorzeichen, Dezimaltrennzeichen) und endet vor dem nächsten Nicht-Zahl-Zeichen. Die Zahl ist damit eindeutig erkennbar und muss nicht mit Begrenzungszeichen markiert werden.

                        Wenn aber eine Zahl aus einer Benutzereingabe stammt und nicht sichergestellt wurde, dass wirklich nur eine Zahl vorliegt (sicherstellen kann man das unter PHP beispielsweise mit einem Typecast zu Integer oder mit intval()), dann kann man diese auch wie einen String behandeln und so notieren, also das volle Programm mit Anführungszeichen und Maskierungsfunktionsaufruf. Eine falsche Zahleneingabe wird dadurch zwar nicht korrigiert und liefert gegebenenfalls fachliche Fehler, kann so aber keinen Schaden durch SQL-Injektion anrichten. Diese Aussage gilt zumindest für MySQL. Andere DBMS verlangen eine ordentliche Zahl-Notation bei Feldern mit nummerischem Typ. Hier muss man dann in der Programmumgebung für eine ausreichende Prüfung und Konvertierung sorgen.

                        Die Quotier- und Maskier-Problematik für SQL-Statements löst sich übrigens beim Einsatz von Prepared Statements in Luft auf, weil mit dieser Technik Statement und Werte getrennte Wege zum DBMS gehen und keine Kontextschachtelung zu berücksichtigen ist. Doch das ist ein anderes Thema und eigentlich nur ein Nebeneffekt von P.S.

                        Wo kann ich mich dazu besser belesen?

                        Im Handbuch zur Syntax des jeweiligen System, speziell im Bereich der von String-Notation handelt.

                        Da ein Handbuch meist nur (s)einen (eigenen) Kontext behandelt, in der Praxis aber Kontexte geschachtelt auftreten, muss man berücksichtigen, wie diese aufgelöst werden können. Am Anfang hat man einen String. Kontext 1 verlangt die Notation des Zeichens LF als \n. Kontext 2 sieht nun die beiden Zeichen \ und n. Aus Sicht von Kontext 2 sind beide getrennt zu betrachten und entsprechend zu notieren. Das \ wird zu \ und das n bleibt wie es ist, weil es kein Sonderzeichen ist. Für Kontext 3 muss man \ \ n nun als \ \ n notieren.

                        Beim Auflösen sieht das System, das den Kontext 3 behandelt, \ \ n und macht daraus \n. System 2 löst \n zu \n auf uns System 1 macht das \n wieder zum LF.

                        Wenn die Systeme unterschiedliche Zeichen mit Sonderbedeutung betrachten, muss auch nur für das jeweilige System/Kontext die entsprechende Umschreibung verwendet werden. Wenn Kontext 2 \ nicht als Sonderzeichen interpretiert, dafür aber ein <, so muss für den Kontext 2 das \ so bleiben und < als &lt; notiert werden (angenommen, die Vorschrift für Kontext 2 sieht das so vor). Für Kontext 3 macht man das eine \ zu \ und lässt die Zeichenfolge &lt; unverändert.

                        Im Prinzip ist es also immer nur wichtig, den jeweiligen Kontext zu identifizieren und jedes Zeichen einzeln für diesen zu betrachten und gegebenenfalls zu behandeln.

                        echo "$verabschiedung $name";

                  2. Hi kEv*!

                    1. ein mit md5 verschlüsseltes Passwort solltest du vorher nicht mit mysql_real_escape_string() behandeln. Es kann vorkommen, dass du dann einen anderen Hash in die Datenbank speicherst, als den vom Originalpasswort generierten Hash.
                      Ok, wird auch geändert.
                      Wenn ich das richtig verstanden habe ...
                      erst escapen und dann durch die md5 Funktion jagen?

                    Ach kEv*... =)
                    Du musst einen mit einer Hashfunktion verschlüsselten String gar nicht escapen. Du bekommst von der md5-Funktion eine 32-stellige Hexadezimalzahl zurück, also Zeichen von 0-9 und a-f. Diese sind völlig ungefährlich.
                    Wenn du schon escapen möchtest, dann erst verschlüsseln und dann escapen: mysql_real_escape_string(md5($password));

                    Beispiel:

                    // Dieses Passwort bekommst du per Post  
                    $password = "3p\A'2gf$"  
                      
                    echo mysql_real_escape_string($password);  
                    // 3p\\A\'2gf$  
                      
                    echo md5(mysql_real_escape_string($password));  
                    // 8c45724d20a85bc0091b16d0e00f61c4  
                      
                    echo md5($password);  
                    // d1d69573cafd4abf2eb9f845b0169856
                    

                    Du siehst also, dass du mit den gleichen Passwörtern unterschiedliche Hashes bekommst.
                    Klar, dass jemand ausgerechnet diese Zeichen in einem Passwort nutzt ist unwahrscheinlich, aber möglich.

                    So kann dir kein Fehler passieren, wenn du das Passwort clientseitig mit md5 verschlüsseln möchtest.

                    MfG H☼psel

                    --
                    "It's amazing I won. I was running against peace, prosperity, and incumbency."
                    George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
                    Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
                    1. Hallo liebe SELFHTMLer,

                      wie wahrscheinlich ist es das das im Klartext übertragene Passwort agefangen wird?
                      Die Js Variante stellt mich vor ein neues Problem.

                      Derzeit prüfe ich auf $_SERVER .... POST usw.
                      nur dann beginne ich die Loginprüfung.

                      Das Javascript müßte ja aber mein Form doch wegschicken und mir den generierten Hash irgendwo als $_POST Variable zur Verfügung stellen.
                      Ich seh es nicht. Oder ich habe mal wieder Tomaten auf den Augen.

                      *grml*
                      LG
                      kev1n

                      --

                      SELFCODE:
                      sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
                      ---
                      1. Hi kEv*!

                        wie wahrscheinlich ist es das das im Klartext übertragene Passwort agefangen wird?

                        Keine Ahnung. Aber allein die Möglichkeit reicht aus. Deine Kontodaten möchtest du doch auch sicher übertragen. Wenn ich ein Passwort eingebe, will ich, dass damit verantwortungsvoll umgegangen wird.

                        Die Js Variante stellt mich vor ein neues Problem.

                        Das war nur ein Vorschlag. Das wäre nur das i-Tüpfelchen. =)

                        Das Javascript müßte ja aber mein Form doch wegschicken und mir den generierten Hash irgendwo als $_POST Variable zur Verfügung stellen.

                        Im Prinzip kannst du den Beispielcode von dem verlinkten Artikel übernehmen. Mit dem Unterschied, dass du das md5-Input-Element auf hidden setzt:
                        <input type="hidden" name="md5_password" value="" />

                        Der Submit-Button muss so aussehen:
                        <input onclick="doChallengeResponse(); return true;" type="submit" name="submitbtn" value="Anmelden" />

                        Serverseitig prüfst du dann, ob das Passwort verschlüsselt übertragen wurde. Wenn ja, dann prüfst du damit in der Datenbank [1], wenn das Feld leer (empty) ist, dann musst du es erst noch verschlüsseln.

                        Ich seh es nicht. Oder ich habe mal wieder Tomaten auf den Augen.

                        Everythink klar?

                        [1] Achtung! Hier _musst_ du mit mysql_real_escape_string escapen! Du MUSST! Hallo, hör mir zu! DU MUSST! ;-)

                        MfG H☼psel

                        --
                        "It's amazing I won. I was running against peace, prosperity, and incumbency."
                        George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
                        Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
                        1. Hallo liebe SELFHTMLer,

                          So korrekt?

                            
                          if (empty($_POST['md5password'])) {  
                               $password = md5($_POST['md5password']);  
                           }  
                           else{  
                            $password = mysql_real_escape_string(md5($_POST['md5password']));  
                           }  
                           $sql = mysql_query("SELECT * FROM user WHERE username = '".mysql_real_escape_string($_POST['username'])."' AND password = '".$password."' LIMIT 1");  
                          
                          

                          Somit habe dann das i-Tüpfelchen.
                          Die andere genannten Punkte werde ich dann heute Abend zu Hause erledigen. :)

                          LG
                          kev1n

                          --

                          SELFCODE:
                          sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
                          ---
                          1. Hallo liebe SELFHTMLer,

                            ~~~php

                            if (empty($_POST['md5password'])) {
                                  $password = md5($_POST['password']);
                              }
                              else{
                               $password = mysql_real_escape_string($_POST['md5password']);
                             }
                              $sql = mysql_query("SELECT * FROM user WHERE username = '".mysql_real_escape_string($_POST['username'])."' AND password = '".$password."' LIMIT 1");

                              
                            LG  
                            kev1n  
                            
                            -- 
                            ![](http://img527.imageshack.us/img527/2329/tweetyog3.jpg)  
                              
                            SELFCODE:  
                            sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|  
                            \---  
                            
                            
                            1. Hi kEv*!

                              So würde ich es machen. =)

                              MfG H☼psel

                              --
                              "It's amazing I won. I was running against peace, prosperity, and incumbency."
                              George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
                              Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
                              1. Hallo liebe SELFHTMLer,

                                Vielen lieben Dank nochmals an alle. Besonderer Dank geht an H☼psel und dedlfix.

                                LG
                                kev1n

                                --

                                SELFCODE:
                                sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|
                                ---