[PHP] PHP Login

Dieses Thema im Forum "Webentwicklung" wurde erstellt von Terrorbeat, 31. August 2008 .

Schlagworte:
  1. 31. August 2008
    PHP Login

    Ich habe Gestern bis 19 Uhr geschlafen und muss jetzt bis heute Abend durch machen damit ich wieder in einem normalen Rhythmus komme. Auf jeden fall helfen Kaffee, Koffeintabletten und Musik nicht mehr und da dachte ich mir, schreibst halt nenn Tutorial für PHP wie man einen guten und Sicheren Login hinbekommt.

    Fangen wir an, wir erstellen uns ein Login Formular mit User und Passwort Feldern:
    HTML:
    <form action="login.php" method="post">
     <table>
     <tr>
     <td>Username</td>
     <td><input name="user" size="40" maxlength="60" value="" /></td>
     </tr>
     <tr>
     <td>Passwort</td>
     <td><input name="pass" type="password" size="40" maxlength="60" /></td>
     </tr>
     <tr>
     <td colspan="2"><input type="submit" value="Abschicken" /></td>
     </tr>
     </table>
    </form>
    
    Müsst ihr eben endsprechend an euer Design anpassen. Nun erstellen wir als erstes unsere Datenbank und Tabellen:
    Code:
    [COLOR="Red"]CREATE DATABASE `login` ;[/COLOR]
    
    CREATE TABLE `user` (
    `ID` INT( 32 ) NOT NULL AUTO_INCREMENT ,
    `user` VARCHAR( 64 ) NOT NULL ,
    `pass` VARCHAR( 32 ) NOT NULL ,
    PRIMARY KEY ( `ID` ) 
    );
    CREATE TABLE `session` (
    `user` INT( 32 ) NOT NULL ,
    `sessionpass` VARCHAR( 32 ) NOT NULL ,
    `login` VARCHAR( 64 ) NOT NULL ,
    INDEX ( `user` ) 
    );
    
    Sauber! Jetzt erstellen wir unsere mysql.php, man sollte immer eine eigene Datei für die Datenbank Verbindung erstellen damit man sie leicht in den verschiedenen Unterseiten includen kann:
    PHP:
    <? php
    $dbHost
    = "localhost" //Hostname des Servers
    $dbUser = "root" //Benutzername
    $dbPass = "" //Passwort
    $dbName = "login" //Name der Datenbank
    //Verbinden und Datenbank auswählen
    $connect =@ mysql_connect ( $dbHost $dbUser $dbPass ) or die( "Konnte keine Verbindung zum Datenbankserver aufbauen!" );
    $selectDB =@ mysql_select_db ( $dbName $connect ) or die( "Konnte die Datenbank <b> $dbName </b> nicht auswählen!" );
    ?>
    Nagut, soweit so gut aber das schwere kommt erst! Es gibt mehrere verschiedene Methoden wie man ein Login Programmieren kann. Die Meisten machen es wohl über Session und Speichern die IP um Sicherheit zu gewehrleisten. Allerdings kann man den User somit nicht dauerhaft eingeloggt lassen da sich die IP ja ändern. Die Alternative dazu sind Cookies. Hier ist das Problem das der User sie ausgeschaltet haben kann. Allerdings kommt das immer seltener vor da es wirklich nur ein geringes Risiko ist die eingeschaltet zu lassen und es doch sehr komfortable ist und die wenigsten Webseites wirklich Funktionieren ohne Cookies. Ein weiteres Problem ist, sobald sich ein Hacker zugriff auf des Users PC verschafft hat kann er diese leicht Kopieren und somit den Login imitieren. Erst mal ist es dann nicht eure schuld wen der User so blöd ist und sich von Hackern verarschen lässt, zweitens wird es dann des Users kleinstes Problem sein das seine Memberstatus auf eurer Webseite von einem anderen besichtigt werden kann. Drittens ist es gefährlich sofern der User Fremdcode auf eure Website schleusen kann was leider nicht selten ist. Wichtig ist auch das falls ihr eine Avatar oder Galerie Funktion anbietet wirklich nur jpg und gif, png Dateien erlaubt sind da bestimmte Bilddateien und andere Dateien gibt die dann Cookies per Email versenden können und somit hat der Hacker eben wiederum den Member Status. Dennoch könnte das alles genau so gut mit allen anderen Login Methoden passieren. Cookies sind meiner Meinung nach einfach die beste Methode einen Login zu gestallten.

    Was wir auf keinen fall machen dürfen ist, jemals des Users Passwort in die Cookies Speichern. Das wäre fatal somit hätte ein Hacker dauerhaft die Möglichkeit sich einzuloggen wen er erst mal das Passwort endschlüsselt hat. Wie gesagt am Anfang macht man viele Sicherheitsfehler. Lest euch Tutorial über Sicherheit durch den PHP ist schwach in Sachen Sicherheit. Wir fangen langsam an, und testen ob Cookies auf des User PC erlaubt sind.
    PHP:
    <? php
    ini_set
    ( 'session.use_only_cookies' '1' );
    session_start ();
    require 
    "mysql.php" ;

    if (empty(
    $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) {
        echo 
    "ERROR! User oder Passwort wurden nicht übergeben!" ;
    } else {

    //HIER GEHT ES DANN WEITER

    }
    ?>
    Zeile 2: Hiermit verbieten wir dem Server die Session über die URL zu geben, "only Cookies". Auf manchen Servern könnte dies zu Fehlern führen, Löscht die Zeile dann einfach.
    Zeile 3: hier starten wir die Session die per Cookies übergeben werden in denen dann die Autorisierung Daten des Users stehen.
    Zeile 4: "require" ist das selbe wie "include" nur das ein Fatal Error ausgegeben wird sobald die Datei nicht includet werden kann. Da die MySql Verbindung für uns Wichtig ist nehmen wir diese variante des includens.
    Zeile 6: Hier überprüfen wir erst mal, ob die Daten die von Nöten sind überhaupt übergeben wurden. Sind sie es nicht, wird eine Fehlermeldung ausgegeben und der User kommt nicht weiter.
    PHP:
    <? php
    ini_set
    ( 'session.use_only_cookies' '1' );
    session_start ();
    require 
    "mysql.php" ;

    if (empty(
    $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) {
        echo 
    "ERROR! User oder Passwort wurden nicht übergeben!" ;
    } else {
        
    $sql  "SELECT pass FROM user WHERE user = '" . $_POST [ 'user' ]. "'" //ggf jeh nach einstellung des servers müsst ihr noch die $post variable durch addslashes oder einer ähnlichen methode absichern.
        
    $res  mysql_query ( $sql ) OR die( mysql_error ());
        if (
    mysql_num_rows ( $res ) !=  "1" ) {
            echo 
    "ERROR! der User wurde nicht gefunden!" ;
        } else {
        
    //HIER GEHT ES DANN WEITER
        
    }
    }
    ?>
    Zeile 9&10: Dies solltet ihr eigentlich alle kennen, ein normaler MySql Query.
    Zeile 11: Hier Checken wir ob die anzahl der gefunden User genau eins beträgt. Also nicht null was dafür stehen würde das der User nicht existiert oder er sein Nick falsch eingegeben hat und auch nicht zwei bis unendlich was dafür stehen würde das es mehrere User mit diesen nick gibt. Also müssen wir bei dem Registration Formular aufpassen das jeder Username nur einmal vergeben werden darf!
    Jeh nach einstellung eure Server müsst ihr die $_Post variable absichern durch addslashes oder sowas. mache ich hier jetzt nicht gibt echt genügend solche tuts.
    PHP:
    <? php
    ini_set
    ( 'session.use_only_cookies' '1' );
    session_start ();
    require 
    "mysql.php" ;

    if (empty(
    $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) {
        echo 
    "ERROR! User oder Passwort wurden nicht übergeben!" ;
    } else {
        
    $sql  "SELECT pass FROM user WHERE user = '" . $_POST [ 'user' ]. "'" ;
        
    $res  mysql_query ( $sql ) OR die( mysql_error ());
        if (
    mysql_num_rows ( $res ) !=  "1" ) {
            echo 
    "ERROR! der User wurde nicht gefunden!" ;
        } else {
            
    $row  mysql_fetch_assoc ( $res );
            if (
    $row [ 'pass' ] !=  md5 ( $_POST [ 'pass' ])) {
                echo 
    "ERROR! das Passwort stimmt nicht!" ;
            } else {
               
    //HIER GEHT ES DANN WEITER!
            
    }
        }
    }
    ?>
    Zeile 14: Hier wird der MySql Query ins array gepackt.
    Zeile 15: Hier wird das eingegeben Passwort in einen md5 hash verschlüsselt und danach überprüft, ob es auch korrekt ist.

    So jetzt wirds grass:
    PHP:
    <? php
    ini_set
    ( 'session.use_only_cookies' '1' );
    session_start ();
    require 
    "mysql.php" ;

    if (empty(
    $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) {
        echo 
    "ERROR! User oder Passwort wurden nicht übergeben!" ;
    } else {
        
    $sql  "SELECT ID, pass FROM user WHERE user = '" . $_POST [ 'user' ]. "'" ;
        
    $res  mysql_query ( $sql ) OR die( mysql_error ());
        if (
    mysql_num_rows ( $res ) !=  "1" ) {
            echo 
    "ERROR! der User wurde nicht gefunden!" ;
        } else {
            
    $row  mysql_fetch_assoc ( $res );
            if (
    $row [ 'pass' ] !=  md5 ( $_POST [ 'pass' ])) {
                echo 
    "ERROR! das Passwort stimmt nicht!" ;
            } else {
                
    $user  $row [ 'ID' ];
                unset(
    $row );
                function 
    password () {
                    
    $abcarray  range ( 'a' 'z' );
                    
    $passarray  array_rand ( $abcarray 12 );
                    
    $password  "" ;
                    foreach(
    $passarray  as  $key  =>  $wert )    {
                        
    $password  .=  $abcarray [ $passarray [ $key ]];
                        
    $password  .=  rand ( 1 , 9 );
                    }
                    
    $password  md5 ( $password );
                    return 
    $password ;
                }
                
    $sessionpass  password ();
                
    //Hier geht es Weiter!
            
    }
        }
    }
    ?>
    Zeile 18 bis 20: Hier Speichern wir die User ID da wir diese Später noch brauchen und Löschen die Passwörter des Users es wäre nur unnötiges Sicherheitsrisiko sie weiterhin gespeichert zu halten. Diese brauchen wir nichtmehr.
    Zeile 21 bis 31: Nun stellt sich die frage, wie wir dem User eigentlich eine einzigartige Erkennung geben können. Viele Anfänger, auch ich damals, glauben das es reichen würde einfach eine Session zu erstellen in der die User ID steht die er nur bekommt sobald er sein Passwort richtig eingegeben hat (was er ja bereits getan hat) was aber jeder zweitklassige Hacker umgehen kann. Wir haben ja bereits festgestellt das die IP eigentlich ehr ungeeignet ist da man jedesmal wen sich die IP ändern neu einloggen muss. Die Funktion die in den Zeilen deklariert wird wählt aus zufälligen Buchstaben und zahlen ein Passwort was wiederum verschlüsselt wird und gibt es zurück. Dieses Speichern wir gleich beim User als Cookie und in der Datenbank. Dann werden wir das bei JEDEM Seiten aufruf miteinander vergleichen ob sie übereinstimmen. Ein Hacker hat somit nur eine Chiangs, wen er Fremdcode in unseren einschleusen kann was wir ohnehin auf jeden fall verhindern müssen! Oder indem er Zugang auf den PC des Users hat aber wie gesagt, das ist nicht unser Problem!
    PHP:
    <? php
    ini_set
    ( 'session.use_only_cookies' '1' );
    session_start ();
    require 
    "mysql.php" ;

    if (empty(
    $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) {
        echo 
    "ERROR! User oder Passwort wurden nicht übergeben!" ;
    } else {
        
    $sql  "SELECT ID, pass FROM user WHERE user = '" . $_POST [ 'user' ]. "'" ;
        
    $res  mysql_query ( $sql ) OR die( mysql_error ());
        if (
    mysql_num_rows ( $res ) !=  "1" ) {
            echo 
    "ERROR! der User wurde nicht gefunden!" ;
        } else {
            
    $row  mysql_fetch_assoc ( $res );
            if (
    $row [ 'pass' ] !=  md5 ( $_POST [ 'pass' ])) {
                echo 
    "ERROR! das Passwort stimmt nicht!" ;
            } else {
                
    $user  $row [ 'ID' ];
                unset(
    $row );
                unset(
    $_POST );
                function 
    password () {
                    
    $abcarray  range ( 'a' 'z' );
                    
    $passarray  array_rand ( $abcarray 12 );
                    
    $password  "" ;
                    foreach(
    $passarray  as  $key  =>  $wert )    {
                        
    $password  .=  $abcarray [ $passarray [ $key ]];
                        
    $password  .=  rand ( 1 , 9 );
                    }
                    
    $password  md5 ( $password );
                    return 
    $password ;
                }
                
    $sessionpass  password ();
                
    $sql  "SELECT user FROM session WHERE user = '" . $user . "'" ;
                
    $res  mysql_query ( $sql ) OR die( mysql_error ());
                if (
    mysql_num_rows ( $res ) !=  "0" ) {
                    
    mysql_query ( "DELETE FROM session where user = '" . $user . "'" ) OR die( mysql_error ());
                }
                
    mysql_query ( "INSERT INTO session (user, sessionpass, login) VALUES ('" . $user . "', '" . $sessionpass . "', '" . time (). "')" ) OR die( mysql_error ());
                
    $_SESSION [ 'user' ] =  $user ;
                
    $_SESSION [ 'sessionpass' ] =  $sessionpass ;
                
    setcookie ( session_name (),  session_id (),  time ()+ 3600 * 24 * 7 * 4 );
                
    Header ( "Location: index.php" );
            }
        }
    }
    ?>
    Zeilen 32 bis 37: Hier überprüfen wir, ob der User bereits eingeloggt war. Wen ja löschen wir seine alte Session da er ja jetzt ein neues Session Passwort bekommen hat und wir dies auch in der Datenbank änder müssen. Da nur der User sein Passwort kennt (oder zummindest kennen sollte) ist er der einzichste, der dazu fähig ist so eine Session neu zu Starten. Sollte ein Hacker also irgentwie an seinen Cookie kommen, wird er nur solange den intern bereich und memberfunktionen nutzen können, bis der eigentliche user sich neu einlogt. Danach müsste der hacker nochmal an den neuen Cookie kommen.
    Zeile 38 bis 42: Hier werden, wie gesagt, die Daten in der Datenbank und beim Klienten gespeichert und zu guter letzt zurück auf die index.php Seite geleitet.



    So das wars dann erstmal mit dem ersten Teil des Tuts. Sorry aber muss jetzt echt pennen gehen bin doch ganz schön müde kann kaum noch denken. Morgen werde ich den rest des tuts Posten der weitaus wichtigere teil! Mods bitte noch nicht schliessen wie gesagt muss es erst fertig schreiben!
     
  2. 9. September 2008
    AW: PHP Login

    Super danke dir vielmals! Habe mich schon oft mit Login-Systemen auseinander gesetzt, aber deins find ich echt gut, scheint auch sicher zu sein!
     
  3. 9. September 2008
    AW: PHP Login

    PHP:
    if (empty( $_POST [ 'user' ]) OR empty( $_POST [ 'pass' ]) OR  trim ( $_POST [ 'user' ]) ==  ""  OR  trim ( $_POST [ 'pass' ]) ==  "" ) { 
    das trim()=='' kannst afaik weglassen, empty macht das.
    dachte du wolltest 'n "sicheres" Login Script machen,
    PHP:
        $sql  "SELECT ID, pass FROM user WHERE user = '" . $_POST [ 'user' ]. "'"
    - escapen?
     
  4. 9. September 2008
    AW: PHP Login

    Das Tutorial find ich super!

    Du hast zwar Punkt und Komma setzen drauf, aber die Absätze solltest du nochmal üben
     
  5. 9. September 2008
    AW: PHP Login

    Er hat ja extra geschrieben:

    Aber ich denke auch, das wenn man schon ein Login Script schreibt direkt auf die Sicherheit achten sollte, daher hätte er auch die paar Zeilen Code auch noch schreiben können.

    Aber für einen Anfänger etc. ist dies sicher kein schlechtes Beispiel
     
  6. 10. September 2008
    AW: PHP Login

    Du solltest es PHP Login nennen, aber nicht sicheres Login, denn das ist es so nicht. Und da du sagst es soll ein Tut sein reicht "man sollte die post vars noch bearbeiten" nicht aus, um dem User zu helfen, schließlich ist es doch an die Anfänger gerichtet, die keine Ahnung haben, was du meinst.
    MfG
     
  7. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.