Session-Timeout nach 5min.

Dieser Commit ist enthalten in:
2025-06-07 22:19:45 +02:00
Ursprung df5e0e0365
Commit 65fe0d4bf5
15 geänderte Dateien mit 508 neuen und 249 gelöschten Zeilen

Datei anzeigen

@@ -1,7 +1,7 @@
import os
import psycopg2
from psycopg2.extras import Json
from flask import Flask, render_template, request, redirect, session, url_for, send_file, jsonify
from flask import Flask, render_template, request, redirect, session, url_for, send_file, jsonify, flash
from flask_session import Session
from functools import wraps
from dotenv import load_dotenv
@@ -25,6 +25,13 @@ app.config['SECRET_KEY'] = os.urandom(24)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['JSON_AS_ASCII'] = False # JSON-Ausgabe mit UTF-8
app.config['JSONIFY_MIMETYPE'] = 'application/json; charset=utf-8'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=5) # 5 Minuten Session-Timeout
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SECURE'] = False # Wird auf True gesetzt wenn HTTPS (intern läuft HTTP)
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
app.config['SESSION_COOKIE_NAME'] = 'admin_session'
# WICHTIG: Session-Cookie soll auch nach 5 Minuten ablaufen
app.config['SESSION_REFRESH_EACH_REQUEST'] = False
Session(app)
# Backup-Konfiguration
@@ -57,6 +64,32 @@ def login_required(f):
def decorated_function(*args, **kwargs):
if 'logged_in' not in session:
return redirect(url_for('login'))
# Prüfe ob Session abgelaufen ist
if 'last_activity' in session:
last_activity = datetime.fromisoformat(session['last_activity'])
time_since_activity = datetime.now() - last_activity
# Debug-Logging
app.logger.info(f"Session check for {session.get('username', 'unknown')}: "
f"Last activity: {last_activity}, "
f"Time since: {time_since_activity.total_seconds()} seconds")
if time_since_activity > timedelta(minutes=5):
# Session abgelaufen - Logout
username = session.get('username', 'unbekannt')
app.logger.info(f"Session timeout for user {username} - auto logout")
# Audit-Log für automatischen Logout (vor session.clear()!)
try:
log_audit('AUTO_LOGOUT', 'session', additional_info={'reason': 'Session timeout (5 minutes)', 'username': username})
except:
pass
session.clear()
flash('Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.', 'warning')
return redirect(url_for('login'))
# Aktivität NICHT automatisch aktualisieren
# Nur bei expliziten Benutzeraktionen (wird vom Heartbeat gemacht)
return f(*args, **kwargs)
return decorated_function
@@ -533,8 +566,10 @@ def login():
if login_success:
# Erfolgreicher Login
session.permanent = True # Aktiviert das Timeout
session['logged_in'] = True
session['username'] = username
session['last_activity'] = datetime.now().isoformat()
reset_login_attempts(ip_address)
log_audit('LOGIN_SUCCESS', 'user',
additional_info=f"Erfolgreiche Anmeldung von IP: {ip_address}")
@@ -569,6 +604,21 @@ def logout():
session.pop('username', None)
return redirect(url_for('login'))
@app.route("/heartbeat", methods=['POST'])
@login_required
def heartbeat():
"""Endpoint für Session Keep-Alive - aktualisiert last_activity"""
# Aktualisiere last_activity nur wenn explizit angefordert
session['last_activity'] = datetime.now().isoformat()
# Force session save
session.modified = True
return jsonify({
'status': 'ok',
'last_activity': session['last_activity'],
'username': session.get('username')
})
@app.route("/")
@login_required
def dashboard():