Login Script Programmierung #Frontend #JavaScript #PHP #Apache #Ubuntu đ Artikel vorlesen lassen Realistische Neural Voice (Edge TTS) Dein Browser unterstĂŒtzt kein HTML5 Audio. Quelle: admin_eintrag_2026-06-12.txt ## Projekt-Architektur und Ordnerstruktur FĂŒr ein schlankes Login-Skript mit Vanilla CSS und Vanilla PHP verfolgen wir eine einfache, aber effektive Architektur. Der Fokus liegt auf ModularitĂ€t und Ăbersichtlichkeit, um die Wartung und Erweiterung zu erleichtern. **Ordnerstruktur:** ``` login-app/ âââ public/ â âââ css/ â â âââ style.css â âââ js/ â â âââ script.js (optional, fĂŒr clientseitige Validierung oder Interaktionen) â âââ index.php (Haupt-Frontend-Datei) âââ src/ â âââ controllers/ â â âââ AuthController.php â âââ models/ â â âââ User.php â âââ views/ â â âââ login.php â â âââ dashboard.php (oder eine andere Erfolgsseite) â âââ database.php (Datenbankverbindungsdetails) âââ .env (Umgebungsvariablen, z.B. DB-Zugangsdaten) âââ composer.json (falls externe Bibliotheken genutzt werden, hier nicht zwingend nötig) âââ README.md ``` **ErlĂ€uterung der Ordnerstruktur:** * **`public/`**: Dies ist das einzige Verzeichnis, das direkt vom Webserver (z.B. Apache, Nginx) aus zugĂ€nglich sein sollte. Es enthĂ€lt alle statischen Assets wie CSS, JavaScript und die Haupt-Frontend-Datei (`index.php`). * **`css/`**: EnthĂ€lt Ihre Vanilla CSS-Dateien. * **`js/`**: EnthĂ€lt Ihre Vanilla JavaScript-Dateien (optional). * **`index.php`**: Der Einstiegspunkt fĂŒr das Frontend. Diese Datei wird die Logik an den `AuthController` delegieren und die entsprechenden Views rendern. * **`src/`**: EnthĂ€lt den serverseitigen PHP-Code. * **`controllers/`**: Hier residiert die Anwendungslogik. Der `AuthController.php` kĂŒmmert sich um die Verarbeitung von Login-Anfragen, die Validierung von Benutzerdaten und die Interaktion mit dem `User`-Modell. * **`models/`**: EnthĂ€lt die Datenmodelle. Das `User.php`-Modell reprĂ€sentiert einen Benutzer und enthĂ€lt Methoden zur Interaktion mit der Datenbank (z.B. Benutzer abrufen, Passwort prĂŒfen). * **`views/`**: EnthĂ€lt die HTML-Templates fĂŒr die verschiedenen Seiten. Diese Dateien sind reine PrĂ€sentationsschichten und sollten so wenig Logik wie möglich enthalten. * **`login.php`**: Das Formular fĂŒr die Benutzeranmeldung. * **`dashboard.php`**: Die Seite, die nach erfolgreichem Login angezeigt wird. * **`database.php`**: Eine zentrale Datei fĂŒr die Datenbankverbindungsparameter. Dies kann entweder direkt in der Datei oder durch Laden aus `.env` erfolgen. * **`.env`**: Eine Datei, die Umgebungsvariablen speichert, wie z.B. Datenbank-Hostname, Benutzername, Passwort und Datenbankname. Dies ist eine bewĂ€hrte Methode, um sensible Daten nicht direkt im Code zu speichern. Diese Datei sollte niemals im Versionskontrollsystem mit eingecheckt werden. * **`composer.json`**: Obwohl fĂŒr dieses einfache Beispiel nicht zwingend erforderlich, ist es eine gute Praxis, Composer fĂŒr die Verwaltung von AbhĂ€ngigkeiten zu nutzen, falls Sie in Zukunft externe PHP-Bibliotheken hinzufĂŒgen möchten. ## Datenbank-Design (SQL) FĂŒr ein Login-Skript benötigen wir mindestens eine Tabelle zur Speicherung der Benutzerdaten. **Tabelle: `users`** | Spaltenname | Datentyp | BeschrĂ€nkungen | Beschreibung | | :-------------- | :-------------- | :------------------- | :------------------------------------------------ | | `id` | `INT` | `PRIMARY KEY`, `AUTO_INCREMENT` | Eindeutige ID fĂŒr jeden Benutzer | | `username` | `VARCHAR(255)` | `NOT NULL`, `UNIQUE` | Benutzername fĂŒr die Anmeldung | | `password_hash` | `VARCHAR(255)` | `NOT NULL` | Gehashter Passwortwert (niemals Klartext speichern!) | | `created_at` | `TIMESTAMP` | `DEFAULT CURRENT_TIMESTAMP` | Zeitstempel der Erstellung des Benutzerkontos | **SQL-Schema (Beispiel fĂŒr MySQL):** ```sql CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` **ErlĂ€uterungen zum Datenbank-Design:** * **`id`**: Eine Auto-inkrementierende Ganzzahl als PrimĂ€rschlĂŒssel ist Standard und sorgt fĂŒr eindeutige Identifikation. * **`username`**: Ein `VARCHAR` fĂŒr den Benutzernamen. `NOT NULL` stellt sicher, dass jeder Benutzer einen Namen hat, und `UNIQUE` verhindert doppelte Benutzernamen. * **`password_hash`**: Dies ist die kritischste Spalte. **Speichern Sie niemals Passwörter im Klartext!** Verwenden Sie starke PHP-Hashing-Funktionen wie `password_hash()` mit `PASSWORD_BCRYPT` oder `PASSWORD_ARGON2ID` fĂŒr die Speicherung. `VARCHAR(255)` ist oft ausreichend, um verschiedene Hashing-Algorithmen und deren Salt zu speichern. * **`created_at`**: Ein Zeitstempel zur Aufzeichnung, wann der Benutzer erstellt wurde. NĂŒtzlich fĂŒr Auditing oder spĂ€tere Analysen. **SicherheitsĂŒberlegungen fĂŒr die Datenbank:** * **SQL-Injection-Schutz**: Verwenden Sie Prepared Statements (mit PDO oder MySQLi) in Ihrem PHP-Code, um SQL-Injection-Angriffe zu verhindern. * **Passwort-Hashing**: Wie bereits erwĂ€hnt, ist die Verwendung sicherer und aktueller Passwort-Hashing-Algorithmen unerlĂ€sslich. * **Datenbank-Zugriffsberechtigungen**: Stellen Sie sicher, dass der Datenbankbenutzer, den Ihre Anwendung verwendet, nur die absolut notwendigen Berechtigungen hat (z.B. `SELECT`, `INSERT`, `UPDATE`, aber keine `DROP` oder `ALTER` auf Produktivsystemen). ## Backend-Core-Logik (Login-Skript) In diesem Abschnitt konzentrieren wir uns auf die Serverseite unseres Login-Skripts. Wir verwenden hierfĂŒr reine PHP-Funktionen, um die Authentifizierung durchzufĂŒhren und die Sitzungsverwaltung zu handhaben. ### 1. Setup und Konfiguration Bevor wir mit der Logik beginnen, richten wir ein einfaches Verzeichnis fĂŒr unser Projekt ein. Angenommen, Ihr Webserver ist bereits konfiguriert, um PHP-Dateien zu verarbeiten. **Projektstruktur:** ``` /projektordner âââ index.php (Das Login-Formular) âââ login_process.php (Die Backend-Logik fĂŒr den Login) âââ secured_page.php (Eine geschĂŒtzte Seite, die nur nach erfolgreichem Login zugĂ€nglich ist) ``` FĂŒr dieses einfache Beispiel speichern wir die Benutzeranmeldeinformationen direkt in einer PHP-Datei. In einer realen Anwendung wĂŒrden Sie eine Datenbank verwenden. **`config.php` (optional, aber gute Praxis):** FĂŒr komplexere Setups könnten Sie eine separate Konfigurationsdatei erstellen, um Datenbankzugangsdaten oder andere Einstellungen zu speichern. FĂŒr dieses Beispiel bleiben wir bei einer einfachen `login_process.php`. ### 2. Authentifizierungslogik (`login_process.php`) Diese Datei ist das HerzstĂŒck unseres Login-Prozesses. Sie empfĂ€ngt die Anmeldedaten vom `index.php`, verifiziert diese und leitet den Benutzer entweder zur geschĂŒtzten Seite weiter oder zeigt eine Fehlermeldung an. ```php <?php // Starten der Sitzung, um Benutzerinformationen ĂŒber Anfragen hinweg zu speichern session_start(); // Einfache Benutzerdatenbank (in der Praxis wĂŒrde dies eine Datenbank sein) $users = [ 'admin' => password_hash('geheimespasswort', PASSWORD_DEFAULT), 'user' => password_hash('anderespasswort', PASSWORD_DEFAULT), ]; // ĂberprĂŒfen, ob die Anfragemethode POST ist if ($_SERVER["REQUEST_METHOD"] == "POST") { // ĂberprĂŒfen, ob die benötigten POST-Variablen vorhanden sind if (isset($_POST['username']) && isset($_POST['password'])) { $username = $_POST['username']; $password = $_POST['password']; // ĂberprĂŒfen, ob der Benutzer existiert und das Passwort korrekt ist if (array_key_exists($username, $users)) { if (password_verify($password, $users[$username])) { // Erfolgreicher Login: Sitzungsvariablen setzen und weiterleiten $_SESSION['loggedin'] = true; $_SESSION['username'] = $username; header("Location: secured_page.php"); exit(); } else { // Falsches Passwort $_SESSION['login_error'] = "UngĂŒltiger Benutzername oder Passwort."; header("Location: index.php"); exit(); } } else { // Benutzer existiert nicht $_SESSION['login_error'] = "UngĂŒltiger Benutzername oder Passwort."; header("Location: index.php"); exit(); } } else { // Fehlende POST-Variablen $_SESSION['login_error'] = "Bitte fĂŒllen Sie beide Felder aus."; header("Location: index.php"); exit(); } } else { // Wenn nicht per POST aufgerufen, zum Login-Formular umleiten header("Location: index.php"); exit(); } ?> ``` **ErlĂ€uterungen:** * **`session_start();`**: Dies ist entscheidend. Es startet eine neue Sitzung oder setzt eine bestehende fort. Sitzungen werden verwendet, um serverseitig Daten zu speichern (wie z.B. ob ein Benutzer angemeldet ist), die ĂŒber mehrere Seitenaufrufe hinweg bestehen bleiben. * **`$users`**: Ein assoziatives Array, das Benutzernamen als SchlĂŒssel und gehashte Passwörter als Werte speichert. **WICHTIG:** Passwörter dĂŒrfen niemals im Klartext gespeichert werden. `password_hash()` erstellt starke, sichere Hashes, und `password_verify()` vergleicht ein eingegebenes Passwort mit einem Hash. * **`$_SERVER["REQUEST_METHOD"] == "POST"`**: Stellt sicher, dass das Skript nur auf Anfragen reagiert, die ĂŒber die POST-Methode gesendet wurden, was fĂŒr FormularĂŒbermittlungen ĂŒblich ist. * **`isset($_POST['username']) && isset($_POST['password'])`**: PrĂŒft, ob die Formularfelder im POST-Request vorhanden sind. * **`password_verify($password, $users[$username])`**: Vergleicht das vom Benutzer eingegebene Passwort mit dem gespeicherten Hash. * **`$_SESSION['loggedin'] = true;`** und **`$_SESSION['username'] = $username;`**: Nach erfolgreicher Authentifizierung werden Sitzungsvariablen gesetzt. `$_SESSION['loggedin']` dient als Flag, um zu prĂŒfen, ob der Benutzer angemeldet ist. * **`header("Location: ...")`**: Dies ist eine HTTP-Header-Umleitung. Sie weist den Browser des Benutzers an, zu einer anderen URL zu navigieren. `exit();` ist wichtig nach einer Umleitung, um sicherzustellen, dass kein weiterer Code ausgefĂŒhrt wird. * **`$_SESSION['login_error']`**: Eine Sitzungsvariable, die verwendet wird, um Fehlermeldungen ĂŒber die Umleitung hinweg zu speichern und im `index.php` anzuzeigen. ### 3. Sitzungsverwaltung und Zugriffskontrolle (`secured_page.php`) Diese Seite ist nur fĂŒr angemeldete Benutzer zugĂ€nglich. Sie nutzt die Sitzungsvariablen, die von `login_process.php` gesetzt wurden. ```php <?php // Starten der Sitzung, um auf bestehende Sitzungsdaten zuzugreifen session_start(); // ĂberprĂŒfen, ob der Benutzer angemeldet ist if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) { // Wenn nicht angemeldet, zum Login-Formular weiterleiten header("Location: index.php"); exit(); } // Wenn der Benutzer angemeldet ist, den Inhalt anzeigen ?> <!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>GeschĂŒtzte Seite</title> <link rel="stylesheet" href="style.css"> <!-- Angenommen, eine style.css existiert --> </head> <body> <div class="container"> <h1>Willkommen, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h1> <p>Dies ist eine geschĂŒtzte Seite, die nur fĂŒr angemeldete Benutzer zugĂ€nglich ist.</p> <p><a href="logout.php">Abmelden</a></p> <!-- Link zu einer Logout-Seite --> </div> </body> </html> ``` **ErlĂ€uterungen:** * **`session_start();`**: Muss auf jeder Seite aufgerufen werden, die auf Sitzungsdaten zugreifen oder diese modifizieren möchte. * **`!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true`**: PrĂŒft, ob die Sitzungsvariable `loggedin` nicht gesetzt ist oder nicht den Wert `true` hat. Wenn dies der Fall ist, ist der Benutzer nicht angemeldet. * **`header("Location: index.php"); exit();`**: Leitet den nicht authentifizierten Benutzer zurĂŒck zum Login-Formular. * **`htmlspecialchars($_SESSION['username'])`**: Dies ist eine wichtige SicherheitsmaĂnahme, um Cross-Site Scripting (XSS)-Angriffe zu verhindern, indem Sonderzeichen im Benutzernamen kodiert werden. ### 4. Abmeldefunktion (`logout.php`) Eine einfache Seite, um die Sitzung zu beenden und den Benutzer abzumelden. ```php <?php // Starten der Sitzung session_start(); // Alle Sitzungsvariablen löschen $_SESSION = array(); // Wenn Sie die Sitzung komplett zerstören wollen, löschen Sie auch das Session-Cookie. // Dies wird empfohlen, da es die Sitzung auf dem Server wirklich beendet. if (ini_get("session.use_cookies")) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] ); } // Die Sitzung zerstören session_destroy(); // ZurĂŒck zum Login-Formular weiterleiten header("Location: index.php"); exit(); ?> ``` **ErlĂ€uterungen:** * **`$_SESSION = array();`**: Leert alle Variablen, die in der aktuellen Sitzung gespeichert sind. * **`setcookie(...)`**: Löscht das Sitzungs-Cookie im Browser des Benutzers. `time() - 42000` setzt das Ablaufdatum in die Vergangenheit, was dem Browser befiehlt, das Cookie zu löschen. * **`session_destroy();`**: Zerstört die Sitzung auf dem Server. ## 3. API-Endpunkte, Hauptfunktionen & Datenverarbeitung Dieses Kapitel beschreibt die serverseitige Logik, die fĂŒr die Authentifizierung von Benutzern in unserer Webanwendung verantwortlich ist. Wir werden die Struktur der API-Endpunkte, die zentralen PHP-Funktionen und die Art und Weise, wie die Daten verarbeitet werden, detailliert erlĂ€utern. ### 3.1. API-Endpunkte FĂŒr das Login-Skript benötigen wir einen einzigen Haupt-API-Endpunkt, der die eingehenden Login-Anfragen entgegennimmt und verarbeitet. Dieser Endpunkt wird typischerweise unter einem Pfad wie `/api/login.php` erreichbar sein. **Tabelle 3.1: Login-API-Endpunkt** | HTTP-Methode | Endpunkt | Beschreibung | | :---------- | :-------------- | :------------------------------------------------- | | `POST` | `/api/login.php` | EmpfĂ€ngt Benutzername und Passwort fĂŒr die Authentifizierung. | **BegrĂŒndung fĂŒr `POST`:** Die `POST`-Methode ist hier die richtige Wahl, da sie dazu dient, Daten an den Server zu senden, um eine Ressource zu erstellen oder zu aktualisieren (in diesem Fall die Authentifizierung eines Benutzers und die Erstellung einer Sitzung). Es ist auĂerdem sicherer als `GET`, da die Daten nicht in der URL sichtbar sind. ### 3.2. Hauptfunktionen (PHP) Die serverseitige Logik wird in einer PHP-Datei (z.B. `login.php` im `api`-Verzeichnis) untergebracht. Diese Datei wird die folgenden Kernfunktionen implementieren: 1. **Anfrage-Validierung und -Bereinigung:** * ĂberprĂŒfen, ob die erforderlichen Daten (`username`, `password`) im `$_POST`-Array vorhanden sind. * Bereinigen der Eingaben, um Cross-Site Scripting (XSS)-Angriffe zu verhindern. Die `htmlspecialchars()`-Funktion ist hierbei essenziell. 2. **Datenbankverbindung:** * Aufbau einer sicheren Verbindung zu unserer Datenbank (z.B. MySQL). Dies sollte idealerweise ĂŒber eine separate Konfigurationsdatei oder eine Datenbank-Klasse erfolgen, um die Zugangsdaten zu schĂŒtzen. 3. **BenutzerprĂŒfung in der Datenbank:** * AusfĂŒhren einer vorbereiteten SQL-Abfrage, um den angegebenen Benutzernamen in der Datenbank zu suchen. Die Verwendung von vorbereiteten Anweisungen (Prepared Statements) ist unerlĂ€sslich, um SQL-Injection-Angriffe zu verhindern. * Vergleich des ĂŒbermittelten Passworts mit dem in der Datenbank gespeicherten, gehashten Passwort. HierfĂŒr wird eine sichere Hashing-Funktion wie `password_verify()` verwendet. 4. **Session-Management:** * Wenn die Anmeldedaten korrekt sind, wird eine Benutzersitzung gestartet (`session_start()`). * Speichern relevanter Benutzerinformationen (z.B. Benutzer-ID, Benutzername) in der `$_SESSION`-Variable. * Setzen eines Session-Cookies (standardmĂ€Ăig von `session_start()` gehandhabt). 5. **Fehlerbehandlung und RĂŒckgabe von Antworten:** * Senden einer geeigneten JSON-Antwort zurĂŒck an den Client, die den Erfolg oder Misserfolg der Anmeldung und gegebenenfalls Fehlerinformationen enthĂ€lt. **Beispielhafter Code-Struktur (`api/login.php`):** ```php <?php // Session starten (falls nicht schon geschehen) if (session_status() == PHP_SESSION_NONE) { session_start(); } // Funktion zur sicheren Datenbankverbindung (wird hier vereinfacht dargestellt) function getDbConnection() { // !!! WICHTIG: Verwenden Sie hier Ihre echten Datenbankzugangsdaten und eine sichere Methode zur Speicherung !!! $host = 'localhost'; $db = 'your_database_name'; $user = 'your_db_user'; $pass = 'your_db_password'; $charset = 'utf8mb4'; $dsn = "mysql:host=$host;dbname=$db;charset=$charset"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { $pdo = new PDO($dsn, $user, $pass, $options); return $pdo; } catch (\PDOException $e) { // In einer echten Anwendung hier eine sicherere Fehlerprotokollierung durchfĂŒhren die('Datenbankverbindung fehlgeschlagen.'); } } // Antwort-Array initialisieren $response = ['success' => false, 'message' => '']; // ĂberprĂŒfen, ob die Anfrage per POST gestellt wurde if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 1. Anfrage-Validierung und -Bereinigung $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING); $password = $_POST['password'] ?? ''; // Passwort wird nicht direkt gefiltert, da es gehasht verglichen wird if (empty($username) || empty($password)) { $response['message'] = 'Benutzername und Passwort sind erforderlich.'; } else { // 2. Datenbankverbindung $pdo = getDbConnection(); // 3. BenutzerprĂŒfung in der Datenbank (mit Prepared Statements) try { $stmt = $pdo->prepare("SELECT id, username, password_hash FROM users WHERE username = :username"); $stmt->bindParam(':username', $username, PDO::PARAM_STR); $stmt->execute(); $user = $stmt->fetch(); // ĂberprĂŒfen, ob ein Benutzer gefunden wurde und das Passwort korrekt ist if ($user && password_verify($password, $user['password_hash'])) { // 4. Session-Management session_regenerate_id(true); // Session-ID neu generieren fĂŒr mehr Sicherheit $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; $_SESSION['logged_in'] = true; $response['success'] = true; $response['message'] = 'Login erfolgreich!'; } else { $response['message'] = 'UngĂŒltiger Benutzername oder Passwort.'; } } catch (PDOException $e) { // In einer echten Anwendung hier eine sicherere Fehlerprotokollierung durchfĂŒhren $response['message'] = 'Ein interner Fehler ist aufgetreten. Bitte versuchen Sie es spĂ€ter erneut.'; error_log("Login error: " . $e->getMessage()); // Nur fĂŒr Debugging, nicht fĂŒr Produktion } } } else { $response['message'] = 'UngĂŒltige Anfrage-Methode.'; } // 5. RĂŒckgabe der Antwort als JSON header('Content-Type: application/json'); echo json_encode($response); ?> ``` ### 3.3. Datenverarbeitung Die Datenverarbeitung auf Serverseite konzentriert sich auf die sichere Handhabung von Anmeldedaten. * **Eingabe:** Der Benutzer gibt seinen Benutzernamen und sein Passwort ĂŒber ein HTML-Formular ein. Diese Daten werden als `POST`-Request an den `/api/login.php`-Endpunkt gesendet. * **Validierung & Sanitization:** * Der **Benutzername** wird mit `filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING)` bereinigt. Dies entfernt potenziell gefĂ€hrliche HTML-Tags und Zeichen, die fĂŒr XSS-Angriffe ausgenutzt werden könnten. * Das **Passwort** wird direkt an die `password_verify`-Funktion ĂŒbergeben. Eine direkte Filterung mit `FILTER_SANITIZE_STRING` wĂ€re hier ungeeignet, da sie Zeichen entfernen könnte, die Teil eines korrekten Passworts sind. Die Sicherheit des Passworts liegt in seiner VerschlĂŒsselung (Hashing) und der sicheren Vergleichsmethode. * **Datenbankinteraktion:** * Die Datenbank speichert **gehashte Passwörter**, niemals Klartextpasswörter. Dies geschieht durch Funktionen wie `password_hash()`, wenn neue Benutzer registriert oder Passwörter zurĂŒckgesetzt werden. * Beim Login vergleicht `password_verify($plain_password, $hashed_password_from_db)` das eingegebene Passwort (im Klartext) mit dem gespeicherten Hash. Diese Funktion kĂŒmmert sich automatisch um das korrekte Hashing-Schema und den Salt. * **Session-Speicherung:** Erfolgreiche Logins fĂŒhren zur Erstellung einer Server-seitigen Session, deren Daten (wie `user_id`, `username`) in der `$_SESSION`-Superglobalen Variable gespeichert werden. Diese Daten sind fĂŒr den Client nicht direkt sichtbar und dienen dazu, den Benutzer ĂŒber mehrere Anfragen hinweg zu identifizieren. Ein Session-Cookie wird vom Browser gespeichert und bei jeder Anfrage an den Server gesendet, um die Sitzung zuzuordnen. * **Ausgabe:** Die Antwort an den Client erfolgt im JSON-Format. Dies ermöglicht es dem JavaScript im Frontend, die Antwort einfach zu parsen und entsprechende Aktionen auszufĂŒhren (z.B. Weiterleitung, Anzeige von Fehlermeldungen). Diese detaillierte Betrachtung der API-Endpunkte, Hauptfunktionen und Datenverarbeitung stellt sicher, dass der Login-Prozess sowohl funktional als auch sicher implementiert ist. ## Frontend-Struktur (HTML/Templates) FĂŒr unsere Login-Anwendung erstellen wir eine einfache HTML-Struktur, die wir mit Vanilla CSS gestalten und mit Vanilla PHP dynamisch rendern werden. Das Ziel ist eine klare Trennung von PrĂ€sentation und Logik. ### `login.html` (Basis-Template) Diese Datei dient als GrundgerĂŒst fĂŒr unsere Login-Seite. Sie enthĂ€lt die notwendigen HTML-Elemente fĂŒr das Formular und Platzhalter fĂŒr Fehlermeldungen oder andere dynamische Inhalte. ```html <!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Login</title> <link rel="stylesheet" href="style.css"> <!-- Link zur CSS-Datei --> </head> <body> <div class="login-container"> <h1>Willkommen zurĂŒck!</h1> <?php // Dieser Block wird von PHP ersetzt, um Fehlermeldungen anzuzeigen if (isset($errorMessage) && !empty($errorMessage)) { echo '<p class="error-message">' . htmlspecialchars($errorMessage) . '</p>'; } ?> <form action="login.php" method="POST"> <!-- Das Formular sendet Daten an login.php --> <div class="form-group"> <label for="username">Benutzername:</label> <input type="text" id="username" name="username" required> </div> <div class="form-group"> <label for="password">Passwort:</label> <input type="password" id="password" name="password" required> </div> <button type="submit">Anmelden</button> </form> <!-- Optional: Link zur Registrierungsseite --> <p>Noch kein Konto? <a href="register.php">Registrieren Sie sich hier.</a></p> </div> </body> </html> ``` **ErlĂ€uterungen:** * **`<!DOCTYPE html>` und `<html>`**: Standard-HTML5-Deklaration. * **`<head>`**: EnthĂ€lt Metadaten, den Titel der Seite und den Link zur CSS-Datei (`style.css`). * **`<body>`**: Der Hauptinhalt der Seite. * **`.login-container`**: Ein div-Container, der das gesamte Login-Formular umschlieĂt und zur Zentrierung und Gestaltung verwendet wird. * **`<h1>`**: Eine HauptĂŒberschrift fĂŒr die Seite. * **PHP-Block fĂŒr Fehlermeldungen**: * Wir verwenden einen einfachen `if`-Block, um zu prĂŒfen, ob die PHP-Variable `$errorMessage` gesetzt und nicht leer ist. * Wenn eine Fehlermeldung vorhanden ist, wird sie in einem `<p>`-Tag mit der Klasse `error-message` ausgegeben. * `htmlspecialchars()` wird verwendet, um Cross-Site-Scripting (XSS) zu verhindern, indem spezielle Zeichen in ihre HTML-EntitĂ€ten umgewandelt werden. * **`<form>`**: * `action="login.php"`: Gibt an, dass die Formulardaten an die Datei `login.php` gesendet werden. * `method="POST"`: Verwendet die POST-Methode, da sensible Daten wie Passwörter gesendet werden. * **`.form-group`**: Ein Container fĂŒr jedes Label-Input-Paar, der die Formatierung erleichtert. * **`<label>`**: Beschriftet die Eingabefelder. Das `for`-Attribut verknĂŒpft das Label mit dem entsprechenden Input-Feld ĂŒber dessen `id`. * **`<input>`**: * `type="text"` fĂŒr den Benutzernamen. * `type="password"` fĂŒr das Passwort, was die Eingabe maskiert. * `id` und `name` sind wichtig fĂŒr die VerknĂŒpfung mit Labels und die Verarbeitung durch PHP. * `required`: Stellt sicher, dass die Felder vor dem Absenden ausgefĂŒllt werden mĂŒssen (Browser-seitige Validierung). * **`<button type="submit">`**: Der Button zum Absenden des Formulars. * **Link zur Registrierung**: Bietet dem Benutzer die Möglichkeit, sich zu registrieren, falls er noch kein Konto hat. Dieses HTML-Template bildet die statische Grundlage. Die Integration von PHP ermöglicht es uns, dynamische Inhalte wie Fehlermeldungen anzuzeigen und das Formular an die entsprechende PHP-Logik weiterzuleiten. Die `style.css` wird im nĂ€chsten Schritt mit den notwendigen Regeln fĂŒr die Gestaltung versehen. ## 5. Premium Vanilla CSS Design (Mobile-First, Animationen) In diesem Kapitel widmen wir uns dem visuellen Erscheinungsbild unseres Login-Skripts. Wir werden einen "Premium Vanilla CSS" Ansatz verfolgen, der sich auf reine CSS-Strukturen, Mobile-First-Designprinzipien und subtile Animationen konzentriert. Das Ziel ist ein sauberes, modernes und responsives Design, das sowohl auf MobilgerĂ€ten als auch auf gröĂeren Bildschirmen gut aussieht und sich gut anfĂŒhlt. ### 5.1. Die Basis: Mobile-First und Grundlegende Stile Wir beginnen mit der Annahme, dass unser Login-Formular zuerst fĂŒr mobile GerĂ€te optimiert wird. Dies bedeutet, dass wir mit den kleinsten Bildschirmen beginnen und unsere Stile schrittweise fĂŒr gröĂere Bildschirme erweitern. #### 5.1.1. `styles.css` - Das HerzstĂŒck unseres Designs Erstellen Sie eine neue Datei namens `styles.css` im selben Verzeichnis wie Ihre `index.php`. Hier definieren wir unsere grundlegenden Stile. ```css /* --- Allgemeine Styles --- */ :root { --primary-color: #6200ea; /* Ein krĂ€ftiges Lila */ --secondary-color: #03dac6; /* Ein TĂŒrkis als Akzent */ --background-color: #f8f9fa; /* Heller Hintergrund */ --text-color: #333; --input-border-color: #ccc; --input-focus-color: var(--primary-color); --button-hover-bg: #5600c8; /* Dunkleres Lila fĂŒr Hover */ --error-color: #e91e63; /* KrĂ€ftiges Pink fĂŒr Fehler */ --success-color: #4caf50; /* GrĂŒn fĂŒr Erfolg */ --font-family-base: 'Roboto', sans-serif; /* Moderner, gut lesbarer Font */ --spacing-unit: 16px; } body { font-family: var(--font-family-base); background-color: var(--background-color); color: var(--text-color); margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; /* Stellt sicher, dass der Body den gesamten Viewport einnimmt */ overflow-x: hidden; /* Verhindert horizontale Scrollbalken */ } /* --- Login Container --- */ .login-container { background-color: #ffffff; padding: calc(var(--spacing-unit) * 2); border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); width: 90%; /* FĂŒr kleine Bildschirme */ max-width: 400px; /* Maximale Breite auf gröĂeren Bildschirmen */ text-align: center; transition: transform 0.3s ease, box-shadow 0.3s ease; /* FĂŒr Animationen */ } .login-container:hover { transform: translateY(-5px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2); } .login-container h2 { margin-top: 0; margin-bottom: var(--spacing-unit); color: var(--primary-color); font-size: 2em; } /* --- Formular-Elemente --- */ .login-form { display: flex; flex-direction: column; gap: var(--spacing-unit); } .form-group { text-align: left; } .form-group label { display: block; margin-bottom: calc(var(--spacing-unit) / 2); font-weight: bold; color: var(--primary-color); } .form-group input[type="text"], .form-group input[type="password"] { width: 100%; padding: var(--spacing-unit); border: 1px solid var(--input-border-color); border-radius: 5px; box-sizing: border-box; /* Stellt sicher, dass Padding und Border in der Breite enthalten sind */ font-size: 1em; transition: border-color 0.3s ease, box-shadow 0.3s ease; } .form-group input:focus { outline: none; border-color: var(--input-focus-color); box-shadow: 0 0 0 3px rgba(98, 0, 234, 0.2); /* Subtiler Fokus-Ring */ } /* --- Buttons --- */ .login-button { background-color: var(--primary-color); color: white; padding: var(--spacing-unit); border: none; border-radius: 5px; font-size: 1.1em; cursor: pointer; transition: background-color 0.3s ease; margin-top: var(--spacing-unit); } .login-button:hover { background-color: var(--button-hover-bg); } /* --- Fehlermeldungen --- */ .error-message { color: var(--error-color); font-size: 0.9em; margin-top: calc(var(--spacing-unit) / 2); text-align: left; } /* --- Erfolg Meldungen --- */ .success-message { color: var(--success-color); font-size: 0.9em; margin-top: calc(var(--spacing-unit) / 2); text-align: left; } /* --- ResponsivitĂ€t: GröĂere Bildschirme --- */ @media (min-width: 600px) { .login-container { padding: calc(var(--spacing-unit) * 3); width: 80%; } .login-container h2 { font-size: 2.5em; } .form-group input[type="text"], .form-group input[type="password"] { padding: calc(var(--spacing-unit) * 1.2); font-size: 1.1em; } .login-button { padding: var(--spacing-unit) * 1.2; font-size: 1.2em; } } ``` **ErlĂ€uterung der Mobile-First-Strategie:** * **Grundlegende Stile:** Die Hauptdefinitionen fĂŒr `body`, `.login-container`, und Formular-Elemente sind fĂŒr kleine Bildschirme gedacht. `width: 90%` und `max-width: 400px` stellen sicher, dass das Formular auf kleinen Bildschirmen fast den gesamten Platz einnimmt, aber nicht ĂŒber eine bestimmte Breite hinausgeht. * **Variablen (`:root`)**: Wir verwenden CSS-Variablen fĂŒr Farben, Schriftarten und AbstĂ€nde. Dies macht das Design konsistent und erleichtert spĂ€tere Anpassungen erheblich. * **Layout (`display: flex`)**: Der `body` wird zu einem Flex-Container, um den Inhalt zentral auszurichten. Der `.login-container` wird ebenfalls zu einem Flex-Container, um die Formularelemente untereinander anzuordnen. * **Box-sizing**: `box-sizing: border-box;` ist essentiell fĂŒr das responsive Design. Es sorgt dafĂŒr, dass Padding und Border zur berechneten Breite eines Elements hinzugerechnet werden, nicht hinzuaddiert. * **Responsiver Teil (`@media (min-width: 600px)`)**: Innerhalb dieser Media Query passen wir die Stile fĂŒr Bildschirme an, die breiter als 600px sind. Hier erhöhen wir die AbstĂ€nde, die SchriftgröĂen und passen die Breite des Containers an, um den gröĂeren Bildschirm besser auszunutzen. ### 5.2. Subtile Animationen fĂŒr ein Premium-GefĂŒhl Animationen können die Benutzererfahrung erheblich verbessern und eine App professioneller wirken lassen. Wir setzen hier auf dezente ĂbergĂ€nge, die dem Benutzer Feedback geben und das Design lebendiger machen. #### 5.2.1. Hover-Effekte * **`.login-container:hover`**: Wenn der Benutzer mit der Maus ĂŒber den Login-Bereich fĂ€hrt, wird er leicht angehoben (`translateY(-5px)`) und der Schatten wird intensiver (`box-shadow`). Dies signalisiert InteraktivitĂ€t. * **`.login-button:hover`**: Der Login-Button Ă€ndert seine Hintergrundfarbe leicht, um das Klicken zu verdeutlichen. * **`.form-group input:focus`**: Beim Fokussieren eines Eingabefeldes wird nicht nur die Border-Farbe geĂ€ndert, sondern auch ein subtiler, halbtransparenter "Ring" um das Feld gelegt. Dies hilft dem Benutzer, das aktive Feld sofort zu erkennen. #### 5.2.2. ĂbergĂ€nge (`transition`) Alle Elemente, bei denen ein Hover- oder Fokus-Effekt stattfindet, haben eine `transition`-Eigenschaft. Dies sorgt dafĂŒr, dass die Ănderungen sanft und animiert erfolgen, anstatt abrupt zu springen. ```css /* Beispiel: Transition fĂŒr den Input-Feld-Fokus */ .form-group input:focus { outline: none; border-color: var(--input-focus-color); box-shadow: 0 0 0 3px rgba(98, 0, 234, 0.2); transition: border-color 0.3s ease, box-shadow 0.3s ease; /* Hier ist die Transition definiert */ } ``` ### 5.3. Integration in `index.php` Nun binden wir unsere `styles.css` in unsere `index.php` ein und strukturieren das HTML entsprechend. ```php <!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Login</title> <!-- Google Fonts (optional, fĂŒr Roboto) --> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="login-container"> <h2>Willkommen zurĂŒck</h2> <?php // Hier kommt Ihre PHP-Logik fĂŒr Fehlermeldungen oder Erfolgsmeldungen if (isset($_GET['error']) && $_GET['error'] === 'invalid_credentials') { echo '<p class="error-message">UngĂŒltiger Benutzername oder Passwort.</p>'; } elseif (isset($_GET['success']) && $_GET['success'] === 'logged_out') { echo '<p class="success-message">Sie wurden erfolgreich abgemeldet.</p>'; } ?> <form action="login.php" method="post" class="login-form"> <div class="form-group"> <label for="username">Benutzername:</label> <input type="text" id="username" name="username" required> </div> <div class="form-group"> <label for="password">Passwort:</label> <input type="password" id="password" name="password" required> </div> <button type="submit" class="login-button">Anmelden</button> </form> </div> </body> </html> ``` **Wichtige HTML-Punkte:** * **`viewport` Meta-Tag**: `width=device-width, initial-scale=1.0` ist entscheidend fĂŒr responsives Design. * **VerknĂŒpfung der CSS-Datei**: `<link rel="stylesheet" href="styles.css">` bindet unsere Stylesheets ein. * **Google Fonts**: Optional, aber Roboto wird oft fĂŒr ein modernes und sauberes Aussehen verwendet. Stellen Sie sicher, dass die Variable `--font-family-base` in `styles.css` entsprechend gesetzt ist. * **HTML-Struktur**: Die Klassen `.login-container`, `.login-form`, `.form-group`, `.login-button` entsprechen exakt den CSS-Selektoren. * **Fehler-/Erfolgsmeldungen**: Ein einfacher Mechanismus wurde hinzugefĂŒgt, um GET-Parameter zu prĂŒfen und entsprechende Meldungen auszugeben. Diese werden dann durch unsere CSS-Klassen `.error-message` und `.success-message` formatiert. Mit diesem Setup haben wir ein visuell ansprechendes, responsives Login-Formular, das auch auf kleineren GerĂ€ten gut funktioniert und durch subtile Animationen ein Premium-GefĂŒhl vermittelt. ## 6. Frontend JS-Logik & Deployment-Befehle (Ubuntu 24.04/Apache) In diesem Kapitel widmen wir uns der Frontend-JavaScript-Logik zur Validierung von Benutzereingaben im Login-Formular und den notwendigen Schritten, um unsere Webanwendung auf einem Ubuntu 24.04 Server mit Apache bereitzustellen. ### 6.1 Frontend JavaScript-Logik FĂŒr eine bessere Benutzererfahrung und zur Vermeidung unnötiger Serveranfragen werden wir clientseitige ValidierungsprĂŒfungen fĂŒr die Login-Felder (Benutzername und Passwort) implementieren. Wir verwenden hierfĂŒr Vanilla JavaScript, um die AbhĂ€ngigkeit von externen Bibliotheken zu minimieren. Erstellen Sie eine neue JavaScript-Datei, z.B. `login.js`, und fĂŒgen Sie folgenden Code hinzu: ```javascript document.addEventListener('DOMContentLoaded', function() { const loginForm = document.getElementById('loginForm'); const usernameInput = document.getElementById('username'); const passwordInput = document.getElementById('password'); const errorMessageDiv = document.getElementById('errorMessage'); loginForm.addEventListener('submit', function(event) { // Verhindert das standardmĂ€Ăige Absenden des Formulars event.preventDefault(); const username = usernameInput.value.trim(); const password = passwordInput.value.trim(); let errors = []; // Validierung des Benutzernamens if (username === '') { errors.push('Benutzername darf nicht leer sein.'); } else if (username.length < 3) { errors.push('Benutzername muss mindestens 3 Zeichen lang sein.'); } // Validierung des Passworts if (password === '') { errors.push('Passwort darf nicht leer sein.'); } else if (password.length < 6) { errors.push('Passwort muss mindestens 6 Zeichen lang sein.'); } // Anzeige von Fehlern oder Absenden des Formulars if (errors.length > 0) { errorMessageDiv.innerHTML = errors.join('<br>'); errorMessageDiv.style.display = 'block'; } else { errorMessageDiv.style.display = 'none'; // Hier wĂŒrde normalerweise das Formular an den Server gesendet werden // Zum Beispiel durch: loginForm.submit(); // FĂŒr dieses Beispiel simulieren wir eine erfolgreiche Validierung alert('Formular erfolgreich validiert! (In der Praxis wird dies an den Server gesendet)'); // loginForm.submit(); // uncomment this to actually submit the form } }); }); ``` **ErlĂ€uterung des JavaScript-Codes:** * `DOMContentLoaded`: Stellt sicher, dass das Skript erst ausgefĂŒhrt wird, wenn das gesamte HTML-Dokument geladen und geparst wurde. * `event.preventDefault()`: Verhindert, dass das Formular standardmĂ€Ăig abgeschickt wird, solange wir die clientseitige Validierung durchfĂŒhren. * `.trim()`: Entfernt fĂŒhrende und nachfolgende Leerzeichen aus den Eingabewerten. * `errors.push()`: FĂŒgt Fehlermeldungen zu einem Array hinzu. * `errorMessageDiv.innerHTML = errors.join('<br>')`: Zeigt alle gesammelten Fehlermeldungen im entsprechenden div an. * `errorMessageDiv.style.display = 'block'/'none'`: Steuert die Sichtbarkeit des Fehlermeldungscontainers. Vergessen Sie nicht, dieses JavaScript in Ihrem HTML-Login-Formular einzubinden, idealerweise vor dem schlieĂenden `</body>`-Tag: ```html <script src="login.js"></script> ``` ### 6.2 Deployment-Befehle (Ubuntu 24.04/Apache) Nachdem wir unsere Login-Anwendung entwickelt haben, ist es Zeit, sie auf einem Server bereitzustellen. Die folgenden Schritte erlĂ€utern, wie Sie Ihre Anwendung auf einem Ubuntu 24.04 Server mit Apache als Webserver einrichten. **Voraussetzungen:** * Ein Server mit Ubuntu 24.04 LTS. * SSH-Zugriff auf den Server. * Root-Privilegien oder `sudo`-Zugriff. **Schritte:** 1. **SSH-Verbindung zum Server herstellen:** ```bash ssh benutzername@ihre_server_ip ``` Ersetzen Sie `benutzername` und `ihre_server_ip` durch Ihre tatsĂ€chlichen Anmeldedaten. 2. **Systempakete aktualisieren:** Es ist immer ratsam, Ihr System auf dem neuesten Stand zu halten. ```bash sudo apt update && sudo apt upgrade -y ``` 3. **Apache Webserver installieren (falls noch nicht geschehen):** Ubuntu 24.04 kommt oft mit Apache vorinstalliert. Falls nicht, installieren Sie es mit: ```bash sudo apt install apache2 -y ``` 4. **Firewall konfigurieren (UFW):** Stellen Sie sicher, dass HTTP (Port 80) und HTTPS (Port 443, falls Sie SSL/TLS verwenden) zugelassen sind. ```bash sudo ufw allow in "Apache Full" sudo ufw enable sudo ufw status ``` 5. **Ihre Webanwendung auf den Server kopieren:** Sie können Ihre Dateien per SFTP (z.B. mit FileZilla) oder ĂŒber `scp` kopieren. Eine ĂŒbliche Stelle fĂŒr Webdateien ist `/var/www/html/`. Angenommen, Ihre Anwendungsdateien befinden sich in einem Ordner namens `my_login_app` auf Ihrem lokalen Rechner, können Sie sie wie folgt kopieren: ```bash # FĂŒhren Sie diesen Befehl auf Ihrem LOKALEN Rechner aus scp -r /pfad/zu/ihrer/lokalen/my_login_app benutzername@ihre_server_ip:/var/www/html/ ``` Ersetzen Sie `/pfad/zu/ihrer/lokalen/my_login_app` durch den tatsĂ€chlichen Pfad zu Ihrem Anwendungsordner. 6. **Dateiberechtigungen anpassen:** Stellen Sie sicher, dass der Apache-Benutzer (normalerweise `www-data`) Lesezugriff auf Ihre Dateien hat. ```bash # Auf dem Server ausfĂŒhren sudo chown -R www-data:www-data /var/www/html/my_login_app sudo chmod -R 755 /var/www/html/my_login_app ``` 7. **Apache-Virtual-Host konfigurieren (Optional, aber empfohlen fĂŒr Produktionsumgebungen):** Anstatt die Standardkonfiguration zu verwenden, ist es besser, eine eigene Virtual-Host-Datei zu erstellen. Dies ist nĂŒtzlich, wenn Sie mehrere Websites auf demselben Server hosten möchten. Erstellen Sie eine neue Konfigurationsdatei: ```bash sudo nano /etc/apache2/sites-available/my_login_app.conf ``` FĂŒgen Sie folgenden Inhalt ein (passen Sie `ServerName` und `DocumentRoot` an): ```apache <VirtualHost *:80> ServerAdmin webmaster@localhost ServerName ihre_domain.com # Oder die IP-Adresse Ihres Servers DocumentRoot /var/www/html/my_login_app <Directory /var/www/html/my_login_app> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/my_login_app_error.log CustomLog ${APACHE_LOG_DIR}/my_login_app_access.log combined </VirtualHost> ``` * Wenn Sie keine Domain haben, können Sie `ServerName` auf die IP-Adresse Ihres Servers setzen. * `AllowOverride All` ist wichtig, wenn Sie `.htaccess`-Dateien verwenden möchten (was wir in diesem einfachen Beispiel nicht tun, aber es ist eine gute Praxis). Aktivieren Sie die neue Site und deaktivieren Sie die Standardseite, falls sie vorhanden ist: ```bash sudo a2ensite my_login_app.conf sudo a2dissite 000-default.conf # Falls Sie die Standardseite nicht benötigen ``` 8. **Apache-Konfiguration testen und neu laden:** ```bash sudo apache2ctl configtest # Wenn die Konfiguration OK ist, neu laden: sudo systemctl reload apache2 ``` Nach diesen Schritten sollte Ihre Login-Anwendung unter der IP-Adresse oder dem Domainnamen Ihres Servers erreichbar sein. Ăffnen Sie Ihren Browser und geben Sie `http://ihre_server_ip/` (oder `http://ihre_domain.com/`) ein.