import os import hashlib import random import time import io import base64 from functools import wraps from flask import session, request, jsonify from PIL import Image, ImageDraw, ImageFont ADMIN_PASSWORD_PLAIN = 'changeme' SECRET_KEY = os.environ.get('SESSION_SECRET', 'dev-secret-change-in-production') def generate_captcha(): """Generiert ein Bild-Captcha mit 4 Zeichen (Zahlen und Buchstaben)""" # 4 zufaellige Zeichen (ohne aehnlich aussehende wie O/0, I/l) chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' code = ''.join(random.choice(chars) for _ in range(4)) # Token fuer Validierung token = hashlib.sha256(f"{code}{int(time.time()/600)}captcha".encode()).hexdigest()[:16] # Antwort in Session speichern session['captcha_answer'] = code session['captcha_token'] = token # Bild generieren img = Image.new('RGB', (180, 60), color='#f8fafc') draw = ImageDraw.Draw(img) # Hintergrund-Noise (Punkte) for _ in range(100): x = random.randint(0, 180) y = random.randint(0, 60) draw.point((x, y), fill='#cbd5e1') # Linien hinzufuegen for _ in range(5): x1 = random.randint(0, 180) y1 = random.randint(0, 60) x2 = random.randint(0, 180) y2 = random.randint(0, 60) draw.line([(x1, y1), (x2, y2)], fill='#94a3b8', width=1) # Text zeichnen (mit leichter Rotation pro Buchstabe) try: font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 36) except: font = ImageFont.load_default() positions = [20, 55, 90, 125] for i, char in enumerate(code): x = positions[i] y = random.randint(12, 18) # Zufaellige Farbe pro Buchstabe color = random.choice(['#1e40af', '#166534', '#9a3412', '#701a75']) draw.text((x, y), char, font=font, fill=color) # Mehr Noise ueber den Text for _ in range(50): x = random.randint(0, 180) y = random.randint(0, 60) draw.point((x, y), fill='#64748b') # In Base64 konvertieren buffer = io.BytesIO() img.save(buffer, format='PNG') img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8') return { "image": f"data:image/png;base64,{img_base64}", "token": token } def verify_captcha(token, answer): """Ueberprueft die Captcha-Antwort""" if not token or not answer: return False stored = session.get('captcha_answer') stored_token = session.get('captcha_token') if stored and stored_token == token and str(stored).upper() == str(answer).upper(): session.pop('captcha_answer', None) session.pop('captcha_token', None) return True return False def require_auth(role='admin'): def decorator(f): @wraps(f) def decorated(*args, **kwargs): if 'user_role' not in session: return jsonify({"error": "Unauthorized"}), 401 if role == 'admin' and session['user_role'] != 'admin': return jsonify({"error": "Admin required"}), 403 return f(*args, **kwargs) return decorated return decorator def check_admin_password(password): return password == ADMIN_PASSWORD_PLAIN