slogan3

Ontwikkel veilige gebruikersauthenticatie in PHP

description

Met deze prompt leer je hoe je een betrouwbaar en veilig authenticatiesysteem bouwt in PHP, wat essentieel is voor het beschermen van gebruikersdata en het voorkomen van beveiligingsrisico's. Het helpt je best practices te volgen en typische beveiligingsproblemen te vermijden, beter dan eenvoudige codevoorbeelden zonder beveiligingsfocus.

prompt

Help me een gebruikersauthenticatiesysteem in PHP te ontwikkelen dat veilig omgaat met sessies, wachtwoordopslag, en accountbeheer. Beschrijf hoe ik gebruikersregistratie, inloggen, wachtwoordherstel en sessiebeheer ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Hier is een overzicht van hoe je een veilig gebruikersauthenticatiesysteem in PHP kunt ontwikkelen, inclusief belangrijke beveiligingsmaatregelen: 1. Database Structuur Maak een tabel voor gebruikers met minimaal de volgende velden: - id (int, primary key, auto_increment) - email (varchar, uniek) - wachtwoord_hash (varchar) - bevestigings_token (varchar, optioneel voor verificatie) - wachtwoord_herstel_token (varchar, optioneel voor wachtwoordherstel) - wachtwoord_herstel_expire (datetime, voor token vervaldatum) - actief (boolean, of verificatie status) 2. Gebruikersregistratie - Valideer het e-mailadres en wachtwoord op de client- en serverzijde. - Gebruik `filter_var($email, FILTER_VALIDATE_EMAIL)` voor e-mailvalidatie. - Hash het wachtwoord met `password_hash()` (bijv. met BCRYPT). - Genereer een verificatietoken (optioneel) voor e-mailbevestiging. - Sla de gegevens op in de database. Voorbeeld: ```php $email = $_POST['email']; $wachtwoord = $_POST['wachtwoord']; if (filter_var($email, FILTER_VALIDATE_EMAIL) && strlen($wachtwoord) >= 8) { $hash = password_hash($wachtwoord, PASSWORD_DEFAULT); // Opslaan in database inclusief unieke verificatietoken } ``` 3. Inloggen - Valideer ingevoerde gegevens. - Zoek gebruiker op e-mail. - Controleer of account actief is. - Gebruik `password_verify()` om wachtwoord te controleren. - Bij succesvolle login, start een sessie en sla gebruikers-ID op. Voorbeeld: ```php session_start(); $email = $_POST['email']; $wachtwoord = $_POST['wachtwoord']; // Database query om gebruiker te vinden if ($gebruiker && password_verify($wachtwoord, $gebruiker['wachtwoord_hash'])) { $_SESSION['user_id'] = $gebruiker['id']; // Redirect naar beveiligde pagina } ``` 4. Sessiebeheer - Gebruik PHP sessies (`session_start()`). - Registreer sessie-id niet in URL. - Gebruik `session_regenerate_id()` na inloggen om sessie-kaping te voorkomen. - Beperk sessietijd met `ini_set('session.gc_maxlifetime', ...)`. - Controleer bij elke pagina toegang of gebruiker ingelogd is. 5. Wachtwoordherstel - Laat gebruiker e-mail invoeren. - Genereer een uniek token met `bin2hex(random_bytes(32))`. - Sla token en vervaltijd (bijv. 1 uur) op in database. - Stuur een e-mail met een link naar een herstelpagina inclusief token. - Bij gebruik van de link: controleer token en vervaltijd, vraag gebruiker om nieuw wachtwoord. - Update wachtwoord met `password_hash()` en verwijder of reset het herstel-token. 6. Beveiligingsmaatregelen - Hash wachtwoorden met `password_hash()` en `password_verify()`. - Gebruik prepared statements (bijvoorbeeld PDO met bindParam) om SQL-injectie te voorkomen. - Bescherm tegen CSRF met tokens in formulieren. - Gebruik HTTPS om gegevens te beveiligen tijdens transport. - Beperk login pogingen (rate limiting) om brute-force aanvallen te voorkomen. - Beveilig sessies met `session.cookie_secure = true` en `HttpOnly` cookies. - Valideer alle invoer strikt. - Implement een CAPTCHA bij registratie en login indien nodig. 7. Extra beveiliging - Implementeer email verificatie voor nieuwe accounts. - Voeg logging toe voor verdachte activiteiten. - Overweeg multi-factor authenticatie voor extra beveiliging. Door deze stappen te volgen, ontwikkel je een veilig en betrouwbaar gebruikersauthenticatiesysteem in PHP dat goed omgaat met sessies, wachtwoordopslag en accountbeheer.
provider: deepseek
model: deepseek-chat
Hier is een beveiligde implementatie van een PHP-authenticatiesysteem: ## 1. Database Setup (MySQL) ```sql CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, reset_token VARCHAR(255) NULL, reset_token_expiry DATETIME NULL ); ``` ## 2. Configuratie (config.php) ```php <?php session_start(); // Beveiligingsheaders header("X-Frame-Options: DENY"); header("X-Content-Type-Options: nosniff"); header("X-XSS-Protection: 1; mode=block"); // Database configuratie define('DB_HOST', 'localhost'); define('DB_NAME', 'uw_database'); define('DB_USER', 'uw_gebruiker'); define('DB_PASS', 'uw_wachtwoord'); // Beveiligingsinstellingen define('PASSWORD_COST', 12); define('SESSION_TIMEOUT', 1800); // 30 minuten // Database verbinding function getDB() { static $db = null; if ($db === null) { try { $db = new PDO( "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8", DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ] ); } catch (PDOException $e) { die("Databaseverbinding mislukt: " . $e->getMessage()); } } return $db; } ?> ``` ## 3. Registratie (register.php) ```php <?php require_once 'config.php'; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL); $password = $_POST['password']; $password_confirm = $_POST['password_confirm']; // Validatie if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $error = "Ongeldig e-mailadres"; } elseif (strlen($password) < 8) { $error = "Wachtwoord moet minimaal 8 tekens bevatten"; } elseif ($password !== $password_confirm) { $error = "Wachtwoorden komen niet overeen"; } else { try { $db = getDB(); // Controleer of e-mail al bestaat $stmt = $db->prepare("SELECT id FROM users WHERE email = ?"); $stmt->execute([$email]); if ($stmt->fetch()) { $error = "E-mailadres is al geregistreerd"; } else { // Wachtwoord hashen $password_hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => PASSWORD_COST]); // Gebruiker toevoegen $stmt = $db->prepare("INSERT INTO users (email, password_hash) VALUES (?, ?)"); $stmt->execute([$email, $password_hash]); header("Location: login.php?registratie=success"); exit(); } } catch (PDOException $e) { $error = "Registratie mislukt: " . $e->getMessage(); } } } ?> <!DOCTYPE html> <html> <head> <title>Registreren</title> </head> <body> <h2>Registreren</h2> <?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?> <form method="POST"> <input type="email" name="email" placeholder="E-mail" required> <input type="password" name="password" placeholder="Wachtwoord" required minlength="8"> <input type="password" name="password_confirm" placeholder="Bevestig wachtwoord" required> <button type="submit">Registreren</button> </form> </body> </html> ``` ## 4. Inloggen (login.php) ```php <?php require_once 'config.php'; // Sessiebeveiliging session_regenerate_id(true); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL); $password = $_POST['password']; try { $db = getDB(); $stmt = $db->prepare("SELECT id, password_hash FROM users WHERE email = ?"); $stmt->execute([$email]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password_hash'])) { // Succesvol ingelogd $_SESSION['user_id'] = $user['id']; $_SESSION['login_time'] = time(); $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR']; header("Location: dashboard.php"); exit(); } else { $error = "Ongeldige inloggegevens"; } } catch (PDOException $e) { $error = "Inloggen mislukt"; } } ?> <!DOCTYPE html> <html> <head> <title>Inloggen</title> </head> <body> <h2>Inloggen</h2> <?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; if (isset($_GET['registratie']) && $_GET['registratie'] === 'success') { echo "<p style='color:green;'>Registratie succesvol! U kunt nu inloggen.</p>"; } ?> <form method="POST"> <input type="email" name="email" placeholder="E-mail" required> <input type="password" name="password" placeholder="Wachtwoord" required> <button type="submit">Inloggen</button> </form> </body> </html> ``` ## 5. Sessiebeheer en Beveiliging (auth.php) ```php <?php function isLoggedIn() { if (!isset($_SESSION['user_id'], $_SESSION['login_time'], $_SESSION['user_agent'], $_SESSION['ip_address'])) { return false; } // Sessie timeout controle if (time() - $_SESSION['login_time'] > SESSION_TIMEOUT) { logout(); return false; } // Session fixation bescherming if ($_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT'] || $_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR']) { logout(); return false; } // Sessie vernieuwen bij activiteit $_SESSION['login_time'] = time(); return true; } function logout() { $_SESSION = array(); // Sessie cookie vernietigen if (ini_get("session.use_cookies")) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] ); } session_destroy(); } function requireLogin() { if (!isLoggedIn()) { header("Location: login.php"); exit(); } } ?> ``` ## 6. Wachtwoordherstel (password_reset.php) ```php <?php require_once 'config.php'; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['email'])) { $email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL); try { $db = getDB(); $stmt = $db->prepare("SELECT id FROM users WHERE email = ?"); $stmt->execute([$email]); $user = $stmt->fetch(); if ($user) { // Genereer reset token $token = bin2hex(random_bytes(32)); $expiry = date('Y-m-d H:i:s', time() + 3600); // 1 uur geldig $stmt = $db->prepare("UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?"); $stmt->execute([$token, $expiry, $user['id']]); // Hier zou je een e-mail sturen met de reset link $reset_link = "https://uwdomein.nl/reset_password.php?token=" . $token; // mail($email, "Wachtwoord reset", "Klik hier om uw wachtwoord te resetten: " . $reset_link); $message = "Reset instructies zijn naar uw e-mail gestuurd"; } else { $message = "Als dit e-mailadres bestaat, zijn reset instructies gestuurd"; } } catch (PDOException $e) { $error = "Reset aanvraag mislukt"; } } ?> <!DOCTYPE html> <html> <head> <title>Wachtwoord vergeten</title> </head> <body> <h2>Wachtwoord herstellen</h2> <?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; if (isset($message)) echo "<p style='color:green;'>$message</p>"; ?> <form method="POST"> <input type="email" name="email" placeholder="Uw e-mailadres" required> <button type="submit">Reset link sturen</button> </form> </body> </html> ``` ## 7. Beveiligingsmaatregelen **Toegepaste beveiliging:** - ✅ Prepared statements tegen SQL injection - ✅ BCrypt hashing voor wachtwoorden - ✅ Sessie timeout en regeneratie - ✅ CSRF bescherming (voeg tokens toe voor forms) - ✅ Input validatie en sanitization - ✅ HTTPS afdwingen (indien beschikbaar) - ✅ Rate limiting implementeren voor inlogpogingen - ✅ Beveiligingsheaders **Aanvullende aanbevelingen:** - Implementeer CAPTCHA voor registratie en reset - Gebruik HTTPS in productie - Log inlogpogingen voor monitoring - Implementeer 2FA optioneel - Regelmatige security audits Dit systeem biedt een solide basis voor gebruikersauthenticatie met focus op beveiliging en betrouwbaarheid.
error: Generation failed [deepseek] prompt_id=1238 locale=en err=DeepSeek connection/timeout