add setup
This commit is contained in:
commit
48179e1f82
7
Dockerfile
Normal file
7
Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM php:8.2-apache
|
||||||
|
|
||||||
|
# Install PDO MySQL driver
|
||||||
|
RUN docker-php-ext-install pdo pdo_mysql mysqli
|
||||||
|
|
||||||
|
# Enable Apache rewrite (optional, but often useful)
|
||||||
|
RUN a2enmod rewrite
|
||||||
19
docker-compose.yaml
Normal file
19
docker-compose.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- ./src:/var/www/html
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: rootpass
|
||||||
|
MYSQL_DATABASE: testdb
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
volumes:
|
||||||
|
- ./database1:/var/lib/mysql
|
||||||
36
setup.sql
Normal file
36
setup.sql
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
-- Datenbank erstellen (falls nicht durch Docker-Umgebung bereits erstellt)
|
||||||
|
CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
USE testdb;
|
||||||
|
|
||||||
|
-- Bank-Tabelle erstellen
|
||||||
|
CREATE TABLE IF NOT EXISTS bank (
|
||||||
|
iban VARCHAR(34) PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
passwd VARCHAR(255) NOT NULL,
|
||||||
|
balance DECIMAL(10, 2) DEFAULT 0.00,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_name (name)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Transaktions-Tabelle erstellen
|
||||||
|
CREATE TABLE IF NOT EXISTS transf (
|
||||||
|
sender VARCHAR(34) NOT NULL,
|
||||||
|
recipient VARCHAR(34) NOT NULL,
|
||||||
|
amount DECIMAL(10, 2) NOT NULL,
|
||||||
|
time INT UNSIGNED NOT NULL,
|
||||||
|
text VARCHAR(500) DEFAULT '',
|
||||||
|
PRIMARY KEY (sender, recipient, time),
|
||||||
|
INDEX idx_sender (sender, time),
|
||||||
|
INDEX idx_recipient (recipient, time),
|
||||||
|
INDEX idx_time (time),
|
||||||
|
FOREIGN KEY (sender) REFERENCES bank(iban) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (recipient) REFERENCES bank(iban) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Test-Accounts erstellen (Passwort: "test123" für alle)
|
||||||
|
INSERT INTO bank (iban, name, passwd, balance) VALUES
|
||||||
|
('DE1234', 'Max Mustermann', '$2y$10$YourHashedPasswordHere1', 5000.00),
|
||||||
|
('DE5678', 'Lisa Schmidt', '$2y$10$YourHashedPasswordHere2', 3500.00),
|
||||||
|
('DE9012', 'Thomas Müller', '$2y$10$YourHashedPasswordHere3', 12000.00)
|
||||||
|
ON DUPLICATE KEY UPDATE balance=balance;
|
||||||
|
|
||||||
728
src/index.php
Normal file
728
src/index.php
Normal file
@ -0,0 +1,728 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* NSCS-Bank - Sichere Version mit Registrierung
|
||||||
|
* Alle Sicherheitslücken behoben + Registrierungs-Feature
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Sicherheits-Konfiguration
|
||||||
|
ini_set('session.cookie_httponly', 1);
|
||||||
|
ini_set('session.cookie_secure', 0); // Auf 1 setzen wenn HTTPS verfügbar
|
||||||
|
ini_set('session.use_strict_mode', 1);
|
||||||
|
ini_set('display_errors', 0); // In Produktion: keine Fehler anzeigen
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Datenbank-Verbindung
|
||||||
|
function getDB() {
|
||||||
|
static $db = null;
|
||||||
|
if ($db === null) {
|
||||||
|
try {
|
||||||
|
$db = new PDO("mysql:host=db;dbname=testdb;charset=utf8mb4", "root", "rootpass", [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||||
|
PDO::ATTR_EMULATE_PREPARES => false
|
||||||
|
]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Datenbankverbindung fehlgeschlagen db: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sicheres Passwort-Hashing
|
||||||
|
function secureHash($password) {
|
||||||
|
return password_hash($password, PASSWORD_ARGON2ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyPassword($password, $hash) {
|
||||||
|
return password_verify($password, $hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF-Token-Management
|
||||||
|
function generateCSRFToken() {
|
||||||
|
if (!isset($_SESSION['csrf_token'])) {
|
||||||
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||||
|
}
|
||||||
|
return $_SESSION['csrf_token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateCSRFToken($token) {
|
||||||
|
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sichere Ausgabe
|
||||||
|
function e($string) {
|
||||||
|
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input-Validierung
|
||||||
|
function validateIBAN($iban) {
|
||||||
|
return preg_match('/^[A-Z0-9]{6,34}$/', $iban);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAmount($amount) {
|
||||||
|
return is_numeric($amount) && $amount >= 1 && $amount <= 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateName($name) {
|
||||||
|
return strlen($name) >= 3 && strlen($name) <= 100 && preg_match('/^[a-zA-ZäöüÄÖÜß\s\-]+$/u', $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session-Prüfung
|
||||||
|
function requireLogin() {
|
||||||
|
if (!isset($_SESSION['iban'])) {
|
||||||
|
header('Location: index.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === REGISTRIERUNG ===
|
||||||
|
if (isset($_GET['act']) && $_GET['act'] == "register") {
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$name = trim($_POST["name"] ?? "");
|
||||||
|
$pass = $_POST["pass"] ?? "";
|
||||||
|
$pass_confirm = $_POST["pass_confirm"] ?? "";
|
||||||
|
|
||||||
|
// Validierung
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if (!validateName($name)) {
|
||||||
|
$errors[] = "Name muss 3-100 Zeichen lang sein und darf nur Buchstaben, Leerzeichen und Bindestriche enthalten";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($pass) < 8) {
|
||||||
|
$errors[] = "Passwort muss mindestens 8 Zeichen haben";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pass !== $pass_confirm) {
|
||||||
|
$errors[] = "Passwörter stimmen nicht überein";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
// Generiere eindeutige IBAN
|
||||||
|
do {
|
||||||
|
$iban = 'DE' . str_pad(rand(0, 999999999999), 12, '0', STR_PAD_LEFT);
|
||||||
|
$stmt = $db->prepare("SELECT COUNT(*) FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$iban]);
|
||||||
|
} while ($stmt->fetchColumn() > 0);
|
||||||
|
|
||||||
|
// Benutzer anlegen
|
||||||
|
try {
|
||||||
|
$hash = secureHash($pass);
|
||||||
|
$stmt = $db->prepare("INSERT INTO bank (iban, name, passwd, balance) VALUES (?, ?, ?, ?)");
|
||||||
|
$stmt->execute([$iban, $name, $hash, 1000.00]); // Startguthaben: 1000€
|
||||||
|
|
||||||
|
$_SESSION['msg'] = "Registrierung erfolgreich! Ihre IBAN: $iban - Startguthaben: 1000€";
|
||||||
|
$_SESSION['reg_iban'] = $iban; // Für Anzeige auf Login-Seite
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$_SESSION['emsg'] = "Registrierung fehlgeschlagen";
|
||||||
|
header("Location: index.php?act=register");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$_SESSION['emsg'] = implode("<br>", $errors);
|
||||||
|
header("Location: index.php?act=register");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Überweisung durchführen ===
|
||||||
|
if (isset($_GET['recv']) && isset($_SESSION['iban'])) {
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
// CSRF-Token prüfen (aus POST)
|
||||||
|
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||||
|
$_SESSION['emsg'] = "Sicherheitsfehler - ungültiges Token";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$recv = trim($_GET['recv']);
|
||||||
|
$amount = $_GET['amount'];
|
||||||
|
$text = trim($_GET['text'] ?? "");
|
||||||
|
|
||||||
|
// Input-Validierung
|
||||||
|
if (!validateIBAN($recv)) {
|
||||||
|
$_SESSION['emsg'] = "Ungültige Empfänger-IBAN";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateAmount($amount)) {
|
||||||
|
$_SESSION['emsg'] = "Ungültiger Betrag (1-1000)";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($text) > 200) {
|
||||||
|
$_SESSION['emsg'] = "Text zu lang (max. 200 Zeichen)";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
// Kontostand prüfen
|
||||||
|
$stmt = $db->prepare("SELECT balance FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$_SESSION["iban"]]);
|
||||||
|
$r = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$r) {
|
||||||
|
header('Location: index.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bal = $r['balance'];
|
||||||
|
if ($bal + 1000 < $amount) {
|
||||||
|
$_SESSION['emsg'] = "Kontostand zu niedrig";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empfängerkonto prüfen
|
||||||
|
$stmt = $db->prepare("SELECT balance FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$recv]);
|
||||||
|
if (!$stmt->fetch()) {
|
||||||
|
$_SESSION['emsg'] = "Empfängerkonto existiert nicht";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transaktion durchführen
|
||||||
|
try {
|
||||||
|
$db->beginTransaction();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("UPDATE bank SET balance = balance - ? WHERE iban = ?");
|
||||||
|
$stmt->execute([$amount, $_SESSION["iban"]]);
|
||||||
|
|
||||||
|
$stmt = $db->prepare("UPDATE bank SET balance = balance + ? WHERE iban = ?");
|
||||||
|
$stmt->execute([$amount, $recv]);
|
||||||
|
|
||||||
|
$stmt = $db->prepare("INSERT INTO transf (sender, recipient, amount, time, text) VALUES (?, ?, ?, ?, ?)");
|
||||||
|
$stmt->execute([$_SESSION["iban"], $recv, $amount, time(), $text]);
|
||||||
|
|
||||||
|
$db->commit();
|
||||||
|
$_SESSION['msg'] = "Überweisung erfolgreich durchgeführt";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$db->rollBack();
|
||||||
|
$_SESSION['emsg'] = "Überweisung fehlgeschlagen";
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$act = $_GET['act'] ?? "";
|
||||||
|
|
||||||
|
// === Passwort ändern ===
|
||||||
|
if ($act == "chpass") {
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||||
|
$_SESSION['emsg'] = "Sicherheitsfehler";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pass = $_POST["pass"] ?? "";
|
||||||
|
|
||||||
|
if (strlen($pass) < 8) {
|
||||||
|
$_SESSION['emsg'] = "Passwort muss mindestens 8 Zeichen haben";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = secureHash($pass);
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("UPDATE bank SET passwd = ? WHERE iban = ?");
|
||||||
|
$stmt->execute([$hash, $_SESSION["iban"]]);
|
||||||
|
|
||||||
|
$_SESSION['msg'] = "Passwort wurde erfolgreich geändert";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Name suchen ===
|
||||||
|
if ($act == "search") {
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||||
|
$_SESSION['emsg'] = "Sicherheitsfehler";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = trim($_POST["name"] ?? "");
|
||||||
|
|
||||||
|
if (strlen($name) > 100) {
|
||||||
|
$_SESSION['emsg'] = "Suchbegriff zu lang";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
// SICHER: Prepared Statement mit LIKE
|
||||||
|
$stmt = $db->prepare("SELECT iban, name FROM bank WHERE name LIKE ? LIMIT 50");
|
||||||
|
$stmt->execute(["%$name%"]);
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
while ($r = $stmt->fetch()) {
|
||||||
|
array_push($a, [$r['iban'], $r['name']]);
|
||||||
|
}
|
||||||
|
$_SESSION['iban_names'] = $a;
|
||||||
|
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Login ===
|
||||||
|
if ($act == "login") {
|
||||||
|
$iban = trim($_POST["iban"] ?? "");
|
||||||
|
$pass = $_POST["pass"] ?? "";
|
||||||
|
|
||||||
|
if (!validateIBAN($iban)) {
|
||||||
|
$_SESSION['emsg'] = "Ungültige IBAN";
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT iban, passwd, name FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$iban]);
|
||||||
|
$r = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($r && verifyPassword($pass, $r['passwd'])) {
|
||||||
|
// Login erfolgreich
|
||||||
|
session_regenerate_id(true); // Session-Fixation verhindern
|
||||||
|
$_SESSION['iban'] = $r['iban'];
|
||||||
|
$_SESSION['name'] = $r['name'];
|
||||||
|
header("Location: index.php?act=main");
|
||||||
|
} else {
|
||||||
|
$_SESSION['emsg'] = "Login fehlgeschlagen - IBAN oder Passwort falsch";
|
||||||
|
header("Location: index.php");
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Logout ===
|
||||||
|
if ($act == "logout") {
|
||||||
|
session_destroy();
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Transfer-Details anzeigen ===
|
||||||
|
if ($act == "showtrans") {
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
$id = $_GET["id"] ?? 0;
|
||||||
|
|
||||||
|
if (!is_numeric($id)) {
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT sender, recipient, amount, time, text FROM transf WHERE time = ?");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$r = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$r) {
|
||||||
|
$_SESSION['emsg'] = "Transaktion nicht gefunden";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfen ob User berechtigt ist diese Transaktion zu sehen
|
||||||
|
if ($r['sender'] !== $_SESSION['iban'] && $r['recipient'] !== $_SESSION['iban']) {
|
||||||
|
$_SESSION['emsg'] = "Keine Berechtigung";
|
||||||
|
header('Location: index.php?act=main');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$src = $r['sender'];
|
||||||
|
$dest = $r['recipient'];
|
||||||
|
$amount = $r['amount'];
|
||||||
|
$text = $r['text'];
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT name FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$src]);
|
||||||
|
$srcn = $stmt->fetch()['name'] ?? "Unbekannt";
|
||||||
|
|
||||||
|
$stmt->execute([$dest]);
|
||||||
|
$destn = $stmt->fetch()['name'] ?? "Unbekannt";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>NSCS-Bank - Sicher</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
padding: 40px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.container-wide {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
h1, h2, h3 { color: #667eea; margin-bottom: 20px; }
|
||||||
|
h1 { font-size: 28px; text-align: center; }
|
||||||
|
.alert {
|
||||||
|
padding: 14px 18px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
animation: slideIn 0.3s ease;
|
||||||
|
}
|
||||||
|
@keyframes slideIn {
|
||||||
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
.alert-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
||||||
|
.alert-danger { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
||||||
|
.alert-info { background: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb; }
|
||||||
|
.form-group { margin-bottom: 20px; }
|
||||||
|
label { display: block; margin-bottom: 8px; font-weight: 600; font-size: 14px; color: #555; }
|
||||||
|
input[type="text"], input[type="password"], input[type="number"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 2px solid #e0e0e0;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
input:focus { outline: none; border-color: #667eea; }
|
||||||
|
.btn {
|
||||||
|
padding: 12px 24px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
.btn-secondary { background: #6c757d; color: white; }
|
||||||
|
.btn-secondary:hover { background: #5a6268; }
|
||||||
|
.btn-outline {
|
||||||
|
background: white;
|
||||||
|
color: #667eea;
|
||||||
|
border: 2px solid #667eea;
|
||||||
|
}
|
||||||
|
.btn-outline:hover {
|
||||||
|
background: #667eea;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.info-box {
|
||||||
|
background: linear-gradient(135deg, #e0e7ff 0%, #f3e7ff 100%);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-left: 5px solid #667eea;
|
||||||
|
}
|
||||||
|
.balance {
|
||||||
|
font-size: 42px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
margin: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.transaction-item {
|
||||||
|
padding: 14px;
|
||||||
|
border: 2px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
.transaction-item:hover {
|
||||||
|
border-color: #667eea;
|
||||||
|
}
|
||||||
|
.search-result {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
hr { border: none; border-top: 2px solid #f0f0f0; margin: 30px 0; }
|
||||||
|
table { border-collapse: collapse; width: 100%; }
|
||||||
|
td { padding: 8px; }
|
||||||
|
.link-text {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.link-text a {
|
||||||
|
color: #667eea;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.link-text a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.feature-list {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 20px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.feature-list li {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container <?php echo ($act == 'main') ? 'container-wide' : ''; ?>">
|
||||||
|
<?php
|
||||||
|
// Nachrichten anzeigen
|
||||||
|
if (isset($_SESSION['msg'])) {
|
||||||
|
echo '<div class="alert alert-success">' . e($_SESSION['msg']) . '</div>';
|
||||||
|
unset($_SESSION['msg']);
|
||||||
|
}
|
||||||
|
if (isset($_SESSION['emsg'])) {
|
||||||
|
echo '<div class="alert alert-danger">' . e($_SESSION['emsg']) . '</div>';
|
||||||
|
unset($_SESSION['emsg']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === REGISTRIERUNGS-SEITE ===
|
||||||
|
if ($act == "register") {
|
||||||
|
?>
|
||||||
|
<h1>🏦 Neues Konto eröffnen</h1>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<strong>📝 Registrierung:</strong>
|
||||||
|
<ul class="feature-list">
|
||||||
|
<li>Automatische IBAN-Generierung</li>
|
||||||
|
<li>Startguthaben: 1.000€</li>
|
||||||
|
<li>Sichere Passwort-Verschlüsselung</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="index.php?act=register">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Vollständiger Name:</label>
|
||||||
|
<input name="name" type="text" required maxlength="100" placeholder="z.B. Max Mustermann">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Passwort (min. 8 Zeichen):</label>
|
||||||
|
<input name="pass" type="password" required minlength="8">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Passwort wiederholen:</label>
|
||||||
|
<input name="pass_confirm" type="password" required minlength="8">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Konto eröffnen</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="link-text">
|
||||||
|
Bereits ein Konto? <a href="index.php">Zum Login</a>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
// === LOGIN-SEITE ===
|
||||||
|
else if ($act == "" || !isset($_SESSION['iban'])) {
|
||||||
|
?>
|
||||||
|
<h1>🏦 NSCS-Bank</h1>
|
||||||
|
|
||||||
|
<?php if (isset($_SESSION['reg_iban'])): ?>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<strong>✅ Ihre neue IBAN:</strong><br>
|
||||||
|
<span style="font-family: monospace; font-size: 18px; font-weight: bold;">
|
||||||
|
<?= e($_SESSION['reg_iban']) ?>
|
||||||
|
</span><br>
|
||||||
|
<small>Bitte notieren Sie sich diese IBAN für den Login!</small>
|
||||||
|
</div>
|
||||||
|
<?php unset($_SESSION['reg_iban']); endif; ?>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<strong>✅ Sicherheitsfeatures:</strong>
|
||||||
|
<ul class="feature-list">
|
||||||
|
<li>Argon2 Passwort-Hashing</li>
|
||||||
|
<li>SQL-Injection-Schutz</li>
|
||||||
|
<li>XSS-Prävention</li>
|
||||||
|
<li>CSRF-Token-Validierung</li>
|
||||||
|
<li>Session-Sicherheit</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="index.php?act=login">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>IBAN:</label>
|
||||||
|
<input name="iban" type="text" required maxlength="34" placeholder="z.B. DE89370400440532013000">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Passwort:</label>
|
||||||
|
<input name="pass" type="password" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Anmelden</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="link-text">
|
||||||
|
Noch kein Konto? <a href="index.php?act=register">Jetzt registrieren</a>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
// === TRANSFER-DETAIL-SEITE ===
|
||||||
|
else if ($act == "showtrans") {
|
||||||
|
?>
|
||||||
|
<h1>Transfer Detail</h1>
|
||||||
|
<div class="info-box">
|
||||||
|
<p><strong>Sender:</strong> <?= e($src) ?> - <?= e($srcn) ?></p>
|
||||||
|
<p><strong>Empfänger:</strong> <?= e($dest) ?> - <?= e($destn) ?></p>
|
||||||
|
<p><strong>Betrag:</strong> <?= e($amount) ?> €</p>
|
||||||
|
<p><strong>Zeit:</strong> <?= e(date('Y-m-d H:i', $id)) ?></p>
|
||||||
|
<p><strong>Text:</strong> <?= e($text) ?></p>
|
||||||
|
</div>
|
||||||
|
<form action="index.php">
|
||||||
|
<input type="hidden" name="act" value="main">
|
||||||
|
<button type="submit" class="btn btn-secondary">Zurück</button>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
// === HAUPTSEITE ===
|
||||||
|
else if ($act == "main") {
|
||||||
|
$name = $_SESSION['name'];
|
||||||
|
$db = getDB();
|
||||||
|
|
||||||
|
$stmt = $db->prepare("SELECT balance FROM bank WHERE iban = ?");
|
||||||
|
$stmt->execute([$_SESSION["iban"]]);
|
||||||
|
$r = $stmt->fetch();
|
||||||
|
$bal = $r['balance'];
|
||||||
|
?>
|
||||||
|
<h1>Hallo <i><?= e($name) ?></i>! 👋</h1>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<p><strong>IBAN:</strong> <span style="font-family: monospace;"><?= e($_SESSION["iban"]) ?></span></p>
|
||||||
|
<p class="balance"><?= e(number_format($bal, 2, ',', '.')) ?> €</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>📋 Überweisungsliste</h2>
|
||||||
|
<?php
|
||||||
|
date_default_timezone_set('Europe/Vienna');
|
||||||
|
$stmt = $db->prepare("SELECT sender, recipient, amount, time FROM transf WHERE (sender = ? OR recipient = ?) AND time > ? ORDER BY time DESC");
|
||||||
|
$stmt->execute([$_SESSION["iban"], $_SESSION["iban"], time() - 10 * 3600]);
|
||||||
|
|
||||||
|
$has_transactions = false;
|
||||||
|
while ($r = $stmt->fetch()) {
|
||||||
|
$has_transactions = true;
|
||||||
|
echo '<div class="transaction-item">';
|
||||||
|
echo e(number_format($r['amount'], 2, ',', '.')) . '€ ' . e($r['sender']) . ' ➔ ' . e($r['recipient']) . ' - ';
|
||||||
|
echo '<a href="index.php?act=showtrans&id=' . e($r['time']) . '" style="color: #667eea;">Detail</a>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$has_transactions) {
|
||||||
|
echo '<p style="text-align: center; color: #999; padding: 20px;">Keine Transaktionen in den letzten 10 Stunden</p>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>💸 Neue Überweisung</h2>
|
||||||
|
<form action="index.php" method="post" onsubmit="this.action='index.php?recv='+this.recv.value+'&amount='+this.amount.value+'&text='+encodeURIComponent(this.text.value); return confirm('Überweisung wirklich durchführen?');">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= e(generateCSRFToken()) ?>">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Empfänger IBAN:</label>
|
||||||
|
<input name="recv" type="text" required maxlength="34">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Betrag (€):</label>
|
||||||
|
<input name="amount" type="number" min="1" max="1000" step="0.01" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Verwendungszweck:</label>
|
||||||
|
<input name="text" type="text" maxlength="200">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Durchführen</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>🔍 IBAN suchen</h2>
|
||||||
|
<form method="post" action="index.php?act=search">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= e(generateCSRFToken()) ?>">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Name:</label>
|
||||||
|
<input name="name" type="text" required maxlength="100">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-secondary">Suchen</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if (isset($_SESSION['iban_names'])) {
|
||||||
|
echo '<div style="margin-top: 15px; background: #f9f9f9; padding: 15px; border-radius: 8px;">';
|
||||||
|
echo '<h3>Suchergebnisse:</h3>';
|
||||||
|
$a = $_SESSION['iban_names'];
|
||||||
|
if (count($a) == 0) {
|
||||||
|
echo '<p style="color: #999;">Keine Ergebnisse gefunden</p>';
|
||||||
|
} else {
|
||||||
|
foreach ($a as $item) {
|
||||||
|
echo '<div class="search-result">' . e($item[0]) . ' - ' . e($item[1]) . '</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
unset($_SESSION['iban_names']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2>🔒 Passwort ändern</h2>
|
||||||
|
<form method="post" action="index.php?act=chpass">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?= e(generateCSRFToken()) ?>">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Neues Passwort (min. 8 Zeichen):</label>
|
||||||
|
<input name="pass" type="password" required minlength="8">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-secondary">Ändern</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form action="index.php?act=logout" method="post">
|
||||||
|
<button type="submit" class="btn btn-outline">Abmelden</button>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user