Login/Registrierung PHP PDO

    • VB.NET

    Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von slice.

      Login/Registrierung PHP PDO

      Titel: Login/Registrierung PHP PDO
      Ja, der Titel sagt es schon ziemlich gut: wir machen ein Login- und Registrierungsskript, für Software und das mit dem PDO (PHP Database Object).
      Was genau das ist? Weiߟ ich ehrlich gesagt nicht. Aber hier eine Erklärung was das ist:
      Das PHP Projekt verfolgt seit kürzerer Zeit die Entwicklung nach OOP (Object Oriented Programing, Objekt Orientierte Programmierung).
      So was ich machen will ist also eigentlich ganz einfach: wir schreiben uns ein Loginskript mit OOP. Klingt schon ungünstig weil PHP - ignorieren wir jetzt einfach mal.

      Natürlich hat dieses Tutorial/whatever auch einige Voraussetzungen die der Server haben MUSS.
      Sind zwa nicht allzuviele aber tragen dennoch viel:
      • PHP 5 und neuer mit aktiviertem PDO für MySQL oder SQLite
      • MySQL Server
      • SQLite

      Das wars.
      Ich werde nicht erklären wie man das PDO für MySQL aktivieren kann, ich sage nur: man findet es in der php.ini!

      Gut für den Clienten nutze ich zwei Methoden:
      • WebClient
      • HTTPPostRequest-Lib

      Letzteres findet man hier im Forum.
      Den Code werde ich soweit es geht nicht in Expander packen. Das Tutorial ist aber zwei Seitig aufgebaut: PHP Skript mit MySQL oder SQLite und der Client Part in VB für WebClient und HTTPPostRequest-Lib. Somit muss ich schon zwei Expander nutzen, ich hoffe das stört jetzt nicht so extrem.

      Also beginnen wir erstmal mit dem PHP Part

      Es sieht am Anfang erstmal schwerer aus, als es ist, dafür funktioniert es später aber deutlich schöner und ist auch in der Wartung deutlich einfacher als die herkömmliche Methode mit dem Login. Wie dem auch sei, gibt es erstmal eine saftige Einleitung zu PHP und PDO:

      Dem PDO ist es ansich egal, welches Datenbanksystem man nutzt - Ist von Vorteil, wenn man viele Datenbanksysteme nutzen will.
      Es geht also nichts über OOP in der PHP Programmierung. Dazu bedienen wir uns auch wirklich nur diesem da der Rest zu komplex würde.
      Ein kleiner Aufbau für eine Abfrage des PDO:

      PHP-Quellcode

      1. $statement = $database->prepare($sqlskript);

      Hier sieht man schon, dass es eindeutig anders wird - man kann meinen komplizierter, aber ich finde es ist deutlich einfacher damit zu arbeiten, also mit anderen Methoden.

      Arbeiten wir den Beispiel-Aufruf mal etwas ab:
      Erster unbekannter Teil: $database.
      Dem PDO ist es vollkommen egal, welche Datenbank es nutzt - der Aufruf ist immer derselbe und verändert sich auch nie.
      Da wir uns nun in der OOP Welt bewegen, müssen wir ein neues Objekt deklarieren und wovon? Richtig, PDO.

      PHP-Quellcode

      1. $database = new PDO()

      Dat wars, hier gehts nicht mehr weiter.
      Wobei..doch hier gehts weiter. Nämlich mit einem kleinen Splitter, zwischen SQLite und MySQL:
      Dem PDO muss man jetzt einen Connection-String übergeben, dieser Unterscheidet sich zwischen MySQL und SQLite erheblich, somit zwei Expander :P
      SQLite

      Connectionstrings in SQLite sind überbewertet :P
      Dieser Teil ist ganz einfach, keine große Erklärung:

      Quellcode

      1. sqlite:datasource=file

      PHP-Quellcode

      1. $databse = new PDO("sqlite:datasource=file");


      MySQL

      Der Connectionstring für eine MySQL Sitzung ist bekanntermaßen so:

      Quellcode

      1. server=adresse;database=datenbank;uid=user;pwd=passwort;
      Und das ist beim PDO nicht anders - wir brauchen nur einen Command, der sagt, welches Datenbanksystem genutzt werden soll.
      Somit sieht unser Connectionstring am Ende so aus:

      Quellcode

      1. mysql:server=server;database=datenbank;uid=user;pwd=passwort

      PHP-Quellcode

      1. $database = new PDO("mysql:server=server;database=datenbank;uid=user;pwd=passwort");



      Fangen wir nun an, die Tabellen zu erstellen. Hierbei werde ich zwischen MySQL und SQLite unterscheiden, nicht aber trennen.
      Der Standardsql-Satz für eine Tabelle ist bekanntlich so:

      SQL-Abfrage

      1. CREATE TABLE IF NOT EXISTS name (spalten)

      Nutzen wir auch gleich aus:
      MySQL:

      SQL-Abfrage

      1. CREATE TABLE IF NOT EXISTS user (uid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username TEXT NOT NULL, password TEXT NOT NULL)

      SQLite:

      SQL-Abfrage

      1. CREATE TABLE IF NOT EXISTS user(uid INT NOT NULL AUTOINCREMENT, username TEXT NOT NULL, password TEXT NOT NULL)


      So und wie nutzen wir das in userem Skript?
      Ganz einfach:

      PHP-Quellcode

      1. $sqlskript = "CREATE TABLE"; // hier oberes einfügen
      2. $statement = $db->prepare($sqlskript); // neues Statement erstellen, damit wir damit weiter arbeiten können
      3. $stm->execute(); // und ausführen

      Damit ist unsere Datenbank erstellt und wir können diese nutzen.

      Weiter mit der Registrierung.
      Hierbei werde ich zwischen MySQL und SQLite nicht unterscheiden, da der SQL String für beide Identisch sein wird.

      Machen wir uns also ans Werk den SQL String zusammenzubasteln: Basis:

      SQL-Abfrage

      1. INSERT INTO tabelle (spalten) VALUES (werte);

      Wir nehmen als Tabelle "user" mit den Spalten: username, password
      Also sieht unser SQL String so aus:

      SQL-Abfrage

      1. INSERT INTO user (username, password) VALUES (werte)

      jezt würd man meinen: okay, nehmen wir doch einfach die Werte die uns geschickt wurden. Ist nicht so gut, könnten SQL Injection mit bei sein.
      Also machen wir was anderes: wir ändern den String nochmal ab:

      SQL-Abfrage

      1. INSERT INTO user (username, password) VALUES (:username, :password)

      Die zwei Parameter mit den Doppelpunkten sind jetzt im Statement drin und werden auch dadrin bleiben.
      Wir müssen diese nurnoch beschreiben. Ist auch wieder, aufgrund der OOP, super einfach.

      PHP-Quellcode

      1. $sql = "INSERT INTO user (username, password) VALUES (:username, :password)";
      2. $statement = $database->prepare($sql);
      3. $statement->bindValue(":username", $_GET['username']); // ich nutze GET, damit ich das im Browser testen kann. Darf gerne für POST umgeschrieben werden.
      4. $statement->bindValue(":password", $_GET['password']); // siehe oben
      5. $statement->execute(); // fertig

      Der User ist eingetragen.
      Wir haben nun aber das Problem, dass wir keine Überprüfung haben, ob Einträge bereits existieren.
      Das ist aber auch ganz einfach eingerichtet :P

      PHP-Quellcode

      1. $sql = "SELECT uid FROM user WHERE lower(username) = lower(:username)";
      2. $statement = $database->prepare($sql);
      3. $statement->bindValue(":username", $_GET['username']);
      4. $statement->execute();
      5. if (count($statement->fetchAll()) > 0)
      6. {
      7. echo '1';
      8. }
      9. else
      10. {
      11. // Registrierungscode hier einfügen
      12. }


      Gut das hätten wir.

      Das Login Skript kommt in den nächsten Posts.
      Genauso wie der VB Code.
      Außerdem werde ich noch ein Skript zusammenbasteln, womit sich das ganz einfach per URL Parameter steuern lässt.
      (db.php?command=login|register|setup).

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „AliveDevil“ ()

      Der Login kommt gleich hinterher :P
      Es ist ebenfalls super einfach ein Loginskript zu basteln.
      Normale Abfrage:

      SQL-Abfrage

      1. SELECT uid, username FROM user WHERE username = wert AND password = password

      Das müssen wir irgendwie in unser PDO-Statement hämmern:

      PHP-Quellcode

      1. $sql = "SELECT uid, username FROM user WHERE lower(username) = lower(:username) AND password = :password";
      2. $statement = $database->prepare($sql);
      3. $statement->bindValue(":username", $_GET['username']);
      4. $statement->bindValue(":password", $_GET['password']);
      5. $statement->execute();
      6. if (count($statement->fetchAll()) == 1)
      7. {
      8. $_SESSION['uid'] = $stm->fetch(PDO::FETCH_ASSOC); // einfach den ersten Teil rausfischen
      9. echo 1;
      10. }
      11. else
      12. echo 0;

      So das wars schon. Jetzt können ja die VB Sachen kommen.
      Die sind mehr oder weniger einfach.

      Für die Registrierung brauchen wir relativ wenig Code. Dafür müssen aber die Skripte so angepasst werden, dass statt $_GET $_POST genutzt wird.

      VB.NET-Quellcode

      1. Using htpR As New HTTPostRequest("url/reg.php")
      2. htpR.Post.Add("username", username)
      3. htpR.Post.Add("password", HashToMd5(password))
      4. Dim retCode As String = htpR.Submit()
      5. if (retCode = "0")
      6. MessageBox.Show("Registrierung erfolgreich.")
      7. elseif (retCode = "1")
      8. MessageBox.Show("Nutzername existiert bereits.")
      9. end if
      10. end using


      Ja...was soll ich dazu noch sagen.
      Login?
      Wird etwas lustiger, da wir mit einem Cookie arbeiten.
      Hier ebenfalls $_GET mit $_POST ersetzen.

      VB.NET-Quellcode

      1. 'Global deklarieren:
      2. Dim cookie As Net.Cookie
      3. ' in Sub oder so:
      4. using htpR As New HTTPPostRequest("url/login.php")
      5. htpR.Post.Add("username", username)
      6. htpR.Post:add("password", HashToMd5(password))
      7. Dim retCode As String = htpR.Submit()
      8. if (retCode = "1")
      9. cookie = htpR.Cookies(0)
      10. MessageBox.Show("Logged in")
      11. else
      12. MessageBox.Show("Login nicht erfolgreich")
      13. end if
      14. end using

      So das wars im Prinzip.
      Wenn ihr jetzt mit eurer Session irgendetwas machen wollt, dann einfach:

      VB.NET-Quellcode

      1. htpR.Cookies.Add(cookie)
      und fertig.
      ich werde später nochmal ein Beispielprojekt sowie die Skripte hochladen.
      Was man jedoch nicht vergessen sollte, ist das vorherige hashen des Passwortes, im aktuellen Beispiel wird es als Plaintext in der Datenbank gespeichert.


      OffTopic-Teil (auf Wunsch) ausgelagert
      -Artentus

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Artentus“ ()