[Tutorial] Login mit Registrierung/Aktivierungsmail

Nerd

kennt sich schon aus
So, erstmal hallo :) an alle, bin ja neu hier.
Um das hier umzustzen brauch ihr einen Server (geht auch lokal), der PHP unterstützt, dafür könnt ihr entweder bei bplaced.net einen mieten oder auch
XAMPP herunterladen, es isntallieren und dann Lokal testen. (Es ist ein Simulierter server. Die .php´s kommen nach XAMPP/htdocs/, und abrufen könnt ihr den Ordner htdocs im BRowser mit http://localhost/, unterordner funktionieren auch).
Des weiteren solltet ihr euch ein wenig in PHP und HTML auskennen, um das Script anzupassen.
Was auchnoch nützlich wäre ist ein gescheiter PHP-Editor, z.B. PHP Coder Pro!(Unten in "infos uzm download" auf den Link klicken,w arten bis der downloadstartet).
Dann mal los.
Zuerst legen wir im phpMyAdmin eine neue Tabelle "users" in einer neuen Datenbank "daten" an. Das geht so:
Zu phpMyAdmin bei bplaced kommt ihr über phpmyadmin.[mein_name].bplaced.net, mit XAMPP über http://localhost/phpmyadmin/ .
Dort loggt ihr euch mit den Daten ein (bei XAMPP ist man schon eingeloggt, wirds auch immer sein), die euch bplaced gegeben hat, abrufbar auch im Login bereich. (Login->MySQL Datenbanken->neue Datenbank, Benutzer ist dann euer bplaced name, ps das eingegebene).
Dort gebt ihr dann bei Neue Datenbank anlegen daten ein, im nächsten Fenster (bei neue Tabelle anlegen) users ein und 4 Felder.
Das erste Feld ist id und der Typ ist INT, die länge ist 2, und bei extra wählt ihr auto_increment aus und hakt den Schlüssel am ende an.
Das Zweite feld ist name, Typ VARCHAR, länge 50, das dritte ist passwort, Type ebenfalss VARCHAR, länge auch 50. Das letzte ist dann email, auch VARCHAR mit 50 zeichen. (Nicht angegebene Werte einfach lassen, wie sie sind).
Fertig, klickt ihr auf speichern.
Dann brauchen wir noch die Tabelle bestatigung mit 2 feldern. 1. acc, INT länge 2, code varchar 50.
Dann gehts mit den HTML dateien los.
An die spätere register.php müssen Folgende Werte:
user -> Der Benutzername
pw1 -> Passwort
pw2 -> Passwortbestätigung
email -> Die E-Mail Adresse
HTML:
---register.html---
<html>
 <head>
  <title>Registrierung</title>
 </head>
 <body>
  <h2>Registrierung</h2>
  <form action="register.php" method="POST">
  <!-- Die Daten werdena n register.php mit POST versant -->
  <a>Benutzername:</a><br>
  <input type="text" name="user"><br>
  <a>Passwort:</a><br>
  <input type="password" name="pw1"><br>
  <a>Passwort bestätigen:</a><br>
  <input type="password" name="pw2"><br>
  <a>E-Mail Adresse (muss gültig sein, KEIN SPAM!)</a><br>
  <input type="text" name="email"><br>
  <input type="submit" value="registreiren">
  </form>
 </body>
</html>
dann werden die Daten wie folgt verarebeitet:
PHP:
---register.php---
<?php
$user=$_POST["user"];
$pw=$_POST["pw1"];
$mail=$_POST["email"];
// Die Daten werden variablen zugewiesen, die wir später verwenden
function checkmail($email) {
// wir könnten hier den host testen, was aber bei 1und1 adressen fehlschlägt
if (strpos($email, "@")) {
    return true;
    // Die E-Mail adresse enthält ein @, also ist sie korekt
} else {
    return false;
    // Sie Enthält kein @, aslo ist sie nicht korrekt
}}
function create() {
   // Funktion zum erstellen des Bestätigungs-Codes
   $create_array=array(
        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
        "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z");
    $create_i=0;
    $created_output="";
    while ($create_i<=15) {
        $create_random=rand(1,26);
        $created_output.=$create_array[$create_random];
        $create_i++;
    }
    return $created_output;
}
//Fangen wir mit der eigentlichen datenverarbeitung an
if ($user!="") {
   // Der Benutzer ist nicht nix
   if ($pw!="" && $pw==$_POST["pw2"]) {
       // Das Passwort ist nicht nichts und stimmt mit dem bestätigungs-üw überein
       if (checkmail($mail)) {
           // Die E-Mail Stimmt
           $db=new mysqli("localhost", "root", "", "daten");
           // Datenbankverbindung

           $sql="INSERT INTO users(id, name, passwort, email) VALUES ('', '".$user."', '".md5($pw)."', '".$mail."')";
           // Befehl, die daten einzutragen
           if (@$db->query($sql)) {
               // Die Daten sind in der Datenbank, jetzt brauchen wir die id des nutzers
               $sql="SELECT id FROM users WHERE name='".$user."'";
               if (@$resultat=$db->query($sql)) {
                   // Daten abgerufen
                   if (@$erbeb=$resultat->fetch_array()) {
                       // Daten als array $ergeb geholt
                       $vcode=create();
                       // bestätigungscode
                       $sql="INSERT INTO bestatigung(acc, code) VALUES ('".$ergeb["id"]."', '".$vcode."')";
                       if (@$db->query($sql)) {
                           // Daten sind inner Datenbank, fertig!
                           @mail($mail, "Registreirung erfolgreich", "Hallo ".$user.",\nDeine Registrierung bei ~ war erfolgreich\nDeine Daten sind:\n".$user."\n".$pw."\n\n Um Deinen account zu aktivieren gehe nach http://deineseite.iwas/verify.php?".$vcode."\n Viele Grüße, dein ~ Team", "From: no-replay@supernaturetutorial.de");
                           //E-Mail an den Nutzer
                           echo "Registrierung Erolgreich. Es wurde eine Mail an ".$mail." gesendet";
                       } else {
                           echo "datenbankprobleme".$db->error;
                       }
                   } else {
                       echo "Datenbankprobleme".$db->error;
                   }
               } else {
                   echo "Datenbankprobleme".$db->error;
               }
           } else {
               echo "Datenbankprobleme".$db->error;
           }
       } else {
           echo "Keine gültige E-Mail Adresse";
       }
    } else {
        echo "die Passwörter stimmen nicht";
    }
} else {
    echo "Kein Benutzer angegeben";
}
@$db->close();
?>
// Schliessen der Datenbankverbindung
Damit steht die registrierung schon fast, bruachen wir nurnoch die bestätigung.
PHP:
---verify.php---
<?php
foreach ($_GET as $key=>$val) {
    $code=$key;
}
// Auslesen der GET-Variable
if (!empty($code)) {
    // Code übergeben
    @$db=new mysqli("localhost", "root", "", "daten");
    // Datenbankverbindung
    $sql="DELETE FROM bestatigung WHERE code='".$code."'";
    if (@$db->query($sql)) {
        echo "Account freigeschaltet";
    } else {
        echo "Datenbankprobleme";
    }
    @$db->close();
} else {
    header ("Location: register.html");
    // Kein Code, auf zu register.html
}
?>
Gut, nun kann man sich registreiren und seinen Account bestätigen
Dann fehlt noch der login
HTML:
---login.html---
<html>
 <head>
  <title>Login</title>
 </head>
 <body>
  <form action="login.php" method="POST">
  <!-- Daten mit POST an login.php -->
  <a>Benutzername:</a><br>
  <input type="text" name="user"><br>
  <a>Passwort</a><br>
  <input type="password" name="pw"><br>
  <input type="submit" value="Login">
  </form>
 </body>
</html>
und login.php
PHP:
---login.php---
<?php
if (isset($_POST["user"]) && isset($_POST["pw"])) {
    $user=$_POST["user"];
    $pw=$_POST["pw"];
    @$db=new mysqli("localhost", "root", "idontwannastop!", "daten");
    $sql="SELECT id,passwort FROM users WHERE name='".$user."'";
    if (@$resultat=$db->query($sql)) {
        if ($ergeb=$resultat->fetch_array()) {
            // Wir kenne die Prozedur ja
            $sql="SELECT acc FROM bestatigung WHERE acc='".$ergeb["id"]."'";
            @$resultat=$db->query($sql);
            @$ergeb2=$resultat->fetch_array();
            if ($ergeb2[0]=="") {
                // Der Account ist Bestätigt
                if (md5($pw)==$ergeb["passwort"]) {
                    // Passwort ok, login
                    session_start();
                    $_SESSION["id"]=$ergeb["id"];
                    $_SESSION["name"]=$user;
                    echo "Eingeloggt";
                } else {
                    echo "Falsches Passwort".$db->error;
                }
            } else {
                echo "Account noch nicht bestätigt";
            }
        } else {
            echo "Der Benutzer ".$user." Existriert nicht";
        }
    } else {
        echo "Der Benutzer ".$user." Existriert nicht";
    }
} else {
    header ("Location: login.html");
}
?>
Das ganze könnt ihr auch als anhang runterladen.
Dann steht das ganze. Ich hoffe, das Tut hat euch geholfen.
Feedback ist herlich willkommen.
Anhang anzeigen Login.zip
EDIT:
Is mir garnich aufgefallen, wer sich einloggt, muss natürlich auch einen Logout-Link vorfinden ;)
Einfach hierdrauf verlinken, zum logut wird nix weiter benötigt.
PHP:
---logout.php---
<?php
// erstmal ne Session starten, damit wir sie auch löschen können
session_start();
// Die Besagte löschen
session_destroy();
header ("Location: login.html");
// und zurück zu login.html
?>
 
Zuletzt bearbeitet:
Tut mir Leid aber dieses Script ist so nicht wirklich zu gebrauchen.

Die Daten werden hier vollkommen ungeprüft übernommen und in die Datenbank geschrieben bzw. ausgelesen. Da ist der Missbrauch schon vorprogrammiert.

Merke: Vertraue keinen Benutzereingaben!
Anleitungen findet man einige im Internet. Beispielsweise hier.
 
Danke für dein Feedback. Ich weis, dass die Spambots das zerfressen, aber mit Captcha&co wird es für Anfänger unbrauchbar, da sie komplett den überblick verlieren.
 
Es geht mir nicht um Captcha & Co sondern um das validieren mit

Code:
<?php
$get=strip_tags($get);
$get=str_replace("\n", "", $get);
$get=trim($get); 
?>

und eine sinnvolle Prüfung der E-Mail Adresse mit

Code:
<?php

if($get=="" || !preg_match('#^([a-zA-Z0-9\.\_\-]+)@([a-zA-Z0-9\.\-]+\.[A-Za-z][A-Za-z]{2,4})$#', $get)){$get='';}

?>

usw., usw..

Ohne ordentliche Prüfungen wird dir ein Hacker in Nullkommanix Schadcode einschleusen können.
 
Und wie du aus HeikeFys Codeschnipseln ersehen kannst, mit $_GET übergeben/übernehmen und nicht mit $_POST. ;)
 
real_escape_string(); habt ihr da auch vergessen. Ich weiss, aber wie gesagt, wird unübersichtlich. Die E-Mail Adresse kann man auch so prüfen:
PHP:
function checkmail($mail) {
    list($user, $domain)=split("@", $mail);
    if (checkdnsrr($domain, "MX") && checkdnsrr($domainm, "A")) {
        return true;
    } else {
        return false;
    }
}
Aber das scheitert an checkdnsrr() u.s.w. Es soll ja ein Tutorial sein, kein fertiges Script.
 
real_escape_string ist veraltet, besser also mysql_real_escape_string verwenden

wenn du die oben von mir verlinkte Seite mal gelesen hättest, hätte dir das auffallen müssen
 
Sorry, ich dachte, mit dem Link meinst du so nen Tut wie ich das grad, anscheinend vergeblich, versucht hab.
 
Hallo Nerd,

es ist absolut nix dagegen einzuwenden, dass sich jemand die Mühe macht, für andere ein Tut zu schreiben und hier zu veröffentlichen.
Ganz im Gegenteil!

Aber die Kritik, die hier kam, richtet sich nicht gegen dich als Person. Sieh es bitte als "konstruktive Erweiterung", denn die Sicherheit einer Anwendung liegt uns - denke ich - allen am Herzen.

Die kurzen "übersichtlichen" Routinen mögen Einsteigern das Lesen erleichtern; wenn aber die Beispiele ohne saubere Prüfung der Eingaben irgendwo übernommen werden, dann freuen sich Hacker und die Anwender müssten sich ärgern.

Grüße
 
Hinzu kommt noch, dass das PW als einfacher MD5 Hash ohne "Salt" gespeichert wird und keine Re-Login-Sperre (z.B. Abbruch uns sperren des PW nach 3 Versuchen) existiert.

Als Adminitrator ist man dafür verantwortlich, dass Benutzerpasswörter sicher gespeichert werden. Der normale Benutzer wählt meistens - gerade bei "unwichtigen" Seiten wie z.B. Foren relativ einfache Passwörter und - was noch schlimmer ist - er verwendet sie häufig auf mehreren Seiten. Einfache Passwörter lassen sich aber ziemlich fix z.B. mit Hilfe von Rainbow Tables aus den MD5 Hashes wieder herstellen (Vielleicht nicht die Originale, aber zumindest funktionierende, was ausreichend ist) ...

Vermeiden lässt sich die Rainbow Attacke ziemlich einfach, indem man ein zusätzliches Feld mit einer Zufallszahl in der DB speichert und diese als Salt zum MD5 Hash hinzu fügt.
Des weiteren sollten die Passwörter eine vorgeschriebene Mindestlänge haben, damit sie nicht mit einfachen Brute-Force oder Lexikon Attacken "erraten" werden können.

Whitespaces sollten auch unter allen Umständen herausgefiltert werden - sowohl normale, als auch codierte - denn sonst kann man evtl. die Schwächen der escape Routinen austricksen und mit doppelt "escapten" und/oder hex-codierten Zeichen beliebigen Code injezieren (ist völlig ohne Whitespaces deutlich schwieriger ;)). Im obigen Beispiel könnte man im login.php unter anderem einfach durch eine passende Eingebe beim Benutzernamen im HTML Form die SQL Select Funktion so erweitern, dass ein beliebiger Benutzernamen mit leerem Passwort selektiert wird - und schon ist man prinzipiell mit jedem x-beliebigen Benutzernamen eingelogt, ohne dass man überhaupt registriert ist.
 
Hm, das das sogar mit dem Login geht hätt ich jetzt nicht gedacht, ich hätte SLQ-Injections nur beim registreiren erwartet. Aber wie wär die Verschlüsselung? Oder kennt die schon jemand?
 
Um es so zu sagen: Ich persönlich würde gar keine eigenen Verschlüsselungs- oder Authentifizierungsroutinen entwerfen sondern z.B. auf pcrypt basierte Lösungen zurückgreifen, die sind i.A. recht gut. Das würde ich auch jedem anderen empfehlen, außer si|e|r ist Sicherheitsexperte und macht ausschließlich solche Sachen, am besten 24h/d.

Gibt auch noch andere Ansätze wie z.B. diesen (en. ) aber da sollte man auch nicht direkt anspringen und den Code üernehmen sondern auch erst einmal die ganzen verlinkten Sachen lesen - ist teilweise schwerer Stoff, lohnt sich aber, wenn wirklich in das Thema Sicherheit einsteigen will ...
 
Also ich hab das auch nur aus Spaß gemacht, das ganze heisst MPBC (MobilePhoneButtonCrypt) weil es in entferntester form auf den Zahlen der Buchstaben auf der Handy Tastatur basiert. Mir is nix besseres eingefallen. So super sicher is es jetzt auch nicht, aber der Verschlüsselte String wird am Ende vor der Ausgabe nochmal basiert auf der länge des eingabewertes verdreht, dazukommt das ich nur 7 Buchstaben verwende, was das ganze zu entschlüsseln erheblich erschwert.
 
Hey, cooles Tutorial. Keine Sorge, ich wills nicht genau so nachbauen, ich weiß ja, dass es unsicher ist. Aber jetzt versteh ich den Code bei mir im CMS Code etwas besser.
Da wird standardmäßig der Realname abgefragt, und ich will das so umbauen, dass nicht mehr danach gefragt wird. Wenn ich einfach das Feld im HTML rausnehme, gibt es eine Fehlermeldung. Wahrscheinlich, weil eine Variable fehlt? Hat jemand eine Idee, was man da noch machen muss?
 
Hallo und herzlich willkommen :)
Wenn Du ein vorgefertigtes CMS verwendest, solltest Du vielleicht den Namen posten, damit man besser helfen kann.
Grundsätzlich solltest Du nicht bei der Abfrage schauen, sondern an der Stelle, an der das Formular abgeschickt wird.
Wenn Du Dir unsicher bist, wo Du schauen musst, kannst Du auch einfach den Quellcode posten.
 
Oben