Vorwort

Diese Anleitung wurde für Schulungszwecke erstellt, weshalb einiges nicht als fertiger Code zur Verfügung steht. Es soll keine Copy-Paste-Übung werden 😅

Sollte etwas unverständlich oder inkorrekt sein, bitte ich um Feedback um es beheben zu können. Nobody is perfect.

Die komplette Ordnerstruktur des Projektes
- | auth
- - | auth.php
- - | changeImage.php
- - | delete.php
- - | editLexikon.php
- - | fetch.php
- - | insert.php
- - | login.php
- - | logout.php
- - | registry.php
- - | secret.php
- | css
- - | custom.css
- | img
- - | Bilder die auf der Seite statisch verwendet werden
- | inc
- - | editEntry.inc.php
- - | liveSearch.inc.php
- - | login.inc.php
- - | loadModal.inc.php
- - | loggedNav.inc.php
- - | saveEntry.inc.php
- | js
- - | liveSearch.js
- | upload-img
- | index.php

Der Login

Das Login Modal in der index.php

Für den Login wurde ein einfaches Bootstrap Modal verwendet. Vergesst auf den Button nicht, der das Modal anzeigt. Innerhalb des Modal Body gibt es eine Form, ebenfalls wieder mit Bootstrap Klassen. Der Login besteht aus dem Feld username und password. Beide Felder sind require, also verpflichtend auszufüllen.

Die action führt zu dem File auth/login.php und übergibt zusätzlich noch den Parameter login mit dem Wert 1

Die Loginlogik in auth/login.php

Prepared Statments: https://www.php-einfach.de/mysql-tutorial/php-prepared-statements/

session_start() erzeugt eine Session oder nimmt die aktuelle wieder auf, die auf der Session-Kennung basiert, die mit einer GET- oder POST-Anfrage oder mit einem Cookie übermittelt wurde. „
-> https://www.php.net/manual/de/function.session-start.php (19.05.2020)

„Die require_once entspricht im Wesentlichen der Funktion require. PHP prüft hier allerdings ob die gewünschte Datei bereits eingebunden wurde und wird sie in diesem Fall nicht ein weiteres mal einbinden.“
-> https://www.php.net/manual/de/function.require-once.php

Mit if(isset($_GET['login'])) überprüfe ich, den Parameter, den ich in der action zusätzlich übergeben habe. Wenn der true ist (also 1), starte ich die Login Prozedur.

Mit htmlspecialchars wandle ich Sonderzeichen in HTML Code um. Mit trim schneide ich sie die umgewandelten Sonderzeichen weg (entfernt Whitespaces und andere Zeichen am Anfang und Ende eines Strings). Das Ergebnis wird jeweils in eine Variable gespeichert.

Wenn die beiden Variablen $username und $password nicht leer sind, wird das SQL Statment aufgebaut. Mit dem prepare-Statement kann ich im dem SQL-Statment Platzhalter vorsehen, in die ich später die Parameter übergebe (bzw. daran binde).

Mit md5(); wird das Passwort in einen Hash verwandelt. Besser ist jedoch password_hash() zu verwenden, da dies einen starken Einweg-Hashing-Algorithmus benutzt.

Mit bind_param('ss', $username, $password); binde ich meine beiden Variablen an die beiden Platzhalter im SQL-Statement. Die Anzahl der „s“ muss die gleiche sein, wie die Anzahl der ? im prepare-Statement und die Variablen müssen in der richtigen Reihenfolge übergeben werden. Mit execute() führe ich das SQL-Statement dann aus.

Mit store_result() wird der Eintrag zwischen gespeichert und mit bind_result($username) wird der Username an die Variable gebunden. Mit der kann dann weiter gearbeitet werden.

In der if-else wird überprüft ob ein Eintrag da ist (wenn nicht, sind die Anmeldedaten nicht korrekt), wenn ja, wird der Username in der Session gespeichert und in den Loginbereich weitergeleitet.
Der var_dump() dient hier nur zum Debuggen und muss im Live-Betrieb gelöscht werden!

Die auth/auth.php im Ordner auth

In der auth.app wird als allererstes eine Session gestartet und überprüft ob die Session einen Eintrag username hat. Wenn dieser nicht vorhanden ist, wird zurück geleitet auf die index.php (Achtung, hier ist mir ein Schreibfehler passiert.
Richtig wäre: header("Location: index.php");

Psssst das ist die Startseite nach dem Login… auth/secret.php

Statt dem include('auth.php'); kann auch require_once('auth.php'); verwendet werden! Erklärung dazu siehe Seitenanfang.

Im Body wird zuerst die Navigation eingebunden. Danach folgt eine Bootstrap Card mit einem Link. Nichts besonderes 😜

Navigation inklusive Login/Logout und Username genannt inc/loggedNav.inc.php

Prinzipiell ist es eine Standardnavigation von Bootstrap mit dem feinen Unterschied, dass gewissen Punkte nur sichtbar sind, wenn man eingeloggt ist. Hierzu gibt es die Abfrage if(!isset($_SESSION["username"])). Deshalb haben wir vorhin den $username in die Session gespeichert, um leichter zu überprüfen ob jemand eingeloggt ist oder nicht. Dementsprechend wird entweder der Link zum Login oder der Link zum Backend und Logout angezeigt.

Außerdem wird am Anfang der Rootpath generiert. Dafür nehmt ihr aus der URL alles zwischen localhost und index.php. Somit kann dann das Logout File leichter aufgerufen werden.

Die Logoutlogik in auth/logout.php

Der Abmeldevorgang ist kurz und schmerzvoll.
Es wird die Session gestartet und dann zerstört mit einem Redirect zur login.php (Achtung hier sollte eigentlich auch header("Location: index.php"); stehen. Wird noch korrigiert.

Die Registrierung

Die Registrierungslogik in auth/registry.php

Zu Beginn wird mit session_start(); die Session generiert und mit require_once('../inc/login.inc.php'); die Datenbankverbindung eingebunden.

Die Registrierungslogik wird über das Registrierungsformular im nächsten Schritt aufgerufen.

Als erstes wird über if(isset($_GET['register'])) überprüft, ob der Parameter existiert und true ist. Die Variable $error wird auf false gesetzt, um im späteren Verlauf mit ihr arbeiten zu können. Sämtliche Eingaben aus dem Registrierungsformular (zu dem wir noch kommen), werden mit der Anweisung trim(htmlspecialchars(...)) bearbeitet.

Vor dem eigentliche abspeichern des neuen Users gibt es noch 4 Überprüfungen:

1: filter_var und FILTER_VALIDATE_EMAIL
Mit PHP kann ein Filter mit entsprechend angegebenen Validator genutzt werden um die Gültigkeit einer Mailadresse zu überprüfen. Es gibt natürlich noch einige weitere Filter:
https://www.php.net/manual/de/filter.filters.validate.php
2. strlen (string length) berechnet die Länge eines Strings. Damit wird in diesem Beispiel überprüft, ob das Passwort nicht leer ist.
3: Passwörter vergleichen
4: Existiert der User schon: Bei diesem Prepared Statement wird lediglich die eMail Adresse zur Überprüfung genommen ob der User bereits existiert, daher ist es sinnvoll, das Feld email in der Datenbank unique zu setzen.

Wenn ihr den Usernamen ebenfalls unique in der Datenbank gesetzt habt, solltet ihr auf jeden Fall diesen vor dem eigentlichen Insert noch überprüfen.

Wenn alle 4 Überprüfungen ohne Fehler bestanden wurden, wird der User mittels einem Prepared Statement in der Datenbank angelegt. Da alle Werte bereits aus dem Post in eine Variable gespeichert sind, muss lediglich das Passwort noch verschlüsselst werden.
Mit $stmt->execute(); wird das Statment ausgeführt und der User in der Datenbank angelegt. Anschließend speichern wir uns den Usernamen noch in der Session und leiten den User ins Backend weiter.

Zum Debuggen ist es hilfreich folgende Anweisung nach dem execute-Statement einzufügen:
printf("Error: %s.\n", $stmt->error);

Das Formular zur auth/registry.php

Das Formular ist wieder ein Standard Bootstrap Formular. Die action verweist auf unser gerade erstelltes File auth/registry.php und übergibt im GET den Parameter register=1 noch mit.