Fehlerausgabe, stiller Mailversand und fehlende Registrierungs-Mail
Drei zusammenhaengende Punkte aus der Analyse des Login-Problems. 1. PHP-Fehler wurden an Besucher ausgegeben display_errors war in impfwarteliste.php (oeffentlich), intern/ impfwarteliste.php, intern/neueanfrage.php, den beiden neueanfrage-old Sicherungen und zeiterfassung/api/vacations.php fest eingeschaltet. Die oeffentliche Impfwarteliste zeigte Patienten bei einem Fatal Error sogar Meldung, Dateipfad und Zeilennummer. Ueberall auf log_errors umgestellt: E_ALL wird weiterhin vollstaendig erfasst, landet aber im Server-Log statt auf der Seite. Der Shutdown-Handler der Impfwarteliste protokolliert die Details und zeigt nur noch einen neutralen Hinweis. Auch register.php gab die rohe Exception-Meldung aus. 2. SendMailMessageSilent() verschluckte jeden Fehler Der catch-Block war leer. Ein SMTP-Ausfall war dadurch von aussen nicht von einem falschen Code zu unterscheiden - der Benutzer landete auf verify_2fa.php und wartete auf eine Mail, die nie kam. Die Funktion protokolliert jetzt und liefert einen bool zurueck. login.php wertet das aus, nimmt bei Fehlschlag den 2FA-Datensatz und die Session-Vormerkung zurueck und sagt es auf der Login-Seite, statt weiterzuleiten. Nebenbei entfernt: ein uebrig gebliebenes echo, das den Mailserver-Namen mitten in die Seite schrieb, sowie ein zweites mysqli_fetch_assoc() auf demselben Result, das nur NULL liefern konnte. 3. register.php verschickte keine Bestaetigungsmail mailreg blieb 0, jeder neue Benutzer landete nach dem Login auf der Aufforderung, die Authentifizierung selbst anzustossen. Die Mail geht jetzt direkt nach der Registrierung raus. Erzeugung und Text liegen in der neuen Funktion sendeAuthentifizierungsMail(), die authmeldung.php ebenfalls benutzt - dort wurde der Rueckgabewert des Versands bisher einer Variablen zugewiesen und nie ausgewertet, die Seite meldete Erfolg auch bei fehlgeschlagenem Versand. Der Versand laeuft nach dem commit(), deshalb prueft der catch-Block in register.php jetzt inTransaction(), bevor er rollBack() aufruft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+13
-6
@@ -8,8 +8,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// Fehler vollstaendig protokollieren, aber nichts davon an Patienten
|
||||||
|
// ausgeben: die Meldungen enthalten Dateipfade und Programmdetails.
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
ini_set('display_errors', '1');
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
register_shutdown_function(static function (): void {
|
register_shutdown_function(static function (): void {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
if ($error === null) {
|
if ($error === null) {
|
||||||
@@ -25,12 +28,16 @@
|
|||||||
header('Content-Type: text/html; charset=utf-8');
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Details ins Server-Log, dem Patienten nur ein neutraler Hinweis.
|
||||||
|
error_log(sprintf(
|
||||||
|
'impfwarteliste.php abgebrochen: %s in %s:%d',
|
||||||
|
(string)$error['message'], (string)$error['file'], (int)$error['line']
|
||||||
|
));
|
||||||
|
|
||||||
echo '<div style="max-width:900px;margin:20px auto;padding:16px;border:3px solid #b30000;background:#fff7f7;color:#111;font-family:Arial,sans-serif;">'
|
echo '<div style="max-width:900px;margin:20px auto;padding:16px;border:3px solid #b30000;background:#fff7f7;color:#111;font-family:Arial,sans-serif;">'
|
||||||
. '<h3 style="margin-top:0;">Fehler in impfwarteliste.php</h3>'
|
. '<h3 style="margin-top:0;">Es ist ein Fehler aufgetreten</h3>'
|
||||||
. '<p>Die Seite ist wegen eines PHP-Fehlers abgebrochen.</p>'
|
. '<p>Die Seite konnte leider nicht vollständig geladen werden. '
|
||||||
. '<p><strong>Meldung:</strong> ' . htmlspecialchars((string)$error['message'], ENT_QUOTES, 'UTF-8') . '<br>'
|
. 'Bitte versuchen Sie es später noch einmal oder rufen Sie uns an.</p>'
|
||||||
. '<strong>Datei:</strong> ' . htmlspecialchars((string)$error['file'], ENT_QUOTES, 'UTF-8') . '<br>'
|
|
||||||
. '<strong>Zeile:</strong> ' . (int)$error['line'] . '</p>'
|
|
||||||
. '</div>';
|
. '</div>';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+72
-9
@@ -2916,17 +2916,75 @@ function loadAktuelleUrlaubsInfo(PDO $pdo): ?array
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erzeugt einen Authentifizierungscode fuer ein intern_users-Konto und schickt
|
||||||
|
* dem Benutzer den Bestaetigungslink.
|
||||||
|
*
|
||||||
|
* Wird von register.php (direkt nach der Anmeldung) und von authmeldung.php
|
||||||
|
* (manuelle Anforderung) benutzt, damit beide denselben Text und dieselbe
|
||||||
|
* Code-Erzeugung verwenden.
|
||||||
|
*
|
||||||
|
* passwortcode_time wird mit NOW() gesetzt, also mit der Uhr des DB-Servers -
|
||||||
|
* authentifizierung.php prueft die Gueltigkeit ebenfalls dort.
|
||||||
|
*
|
||||||
|
* @return bool true, wenn die Mail uebergeben werden konnte
|
||||||
|
*/
|
||||||
|
function sendeAuthentifizierungsMail(PDO $pdo, array $user, string $organisationsname): bool
|
||||||
|
{
|
||||||
|
$passwortcode = random_string();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
UPDATE intern_users
|
||||||
|
SET passwortcode = :passwortcode, passwortcode_time = NOW()
|
||||||
|
WHERE id = :userid
|
||||||
|
");
|
||||||
|
$stmt->execute([
|
||||||
|
'passwortcode' => sha1($passwortcode),
|
||||||
|
'userid' => $user['id']
|
||||||
|
]);
|
||||||
|
|
||||||
|
$url = getSiteURL() . 'authentifizierung.php?userid=' . urlencode((string)$user['id'])
|
||||||
|
. '&code=' . urlencode($passwortcode);
|
||||||
|
|
||||||
|
$betreff = 'Authentifizierung für Ihren Account bei ' . $organisationsname;
|
||||||
|
|
||||||
|
$text = 'Hallo ' . htmlentities((string)$user['vorname']) . ',<br><br>
|
||||||
|
für die Nutzung des Kontos müssen Sie das Konto per E-Mail authentifizieren. Dazu klicken Sie auf den folgenden Link:<br>
|
||||||
|
' . $url . '
|
||||||
|
<br><br>
|
||||||
|
Nach der Authentifizierung können Sie das Konto vollumfänglich nutzen.<br><br>
|
||||||
|
Haben Sie kein Konto bei uns angelegt, ignorieren Sie diese E-Mail.<br><br>
|
||||||
|
|
||||||
|
Viele Grüße,<br>
|
||||||
|
Ihr ' . $organisationsname . ' Team';
|
||||||
|
|
||||||
|
return SendMailMessage($pdo, (string)$user['email'], $betreff, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verschickt eine Mail, ohne die aufrufende Seite abzubrechen.
|
||||||
|
* "Silent" heisst: keine Ausgabe und keine Exception nach aussen - der Fehler
|
||||||
|
* landet aber im Server-Log, und der Rueckgabewert sagt, ob es geklappt hat.
|
||||||
|
* Frueher wurde jeder Fehler ersatzlos verschluckt; ein stiller SMTP-Ausfall
|
||||||
|
* war dadurch von aussen nicht von einem falschen Code zu unterscheiden.
|
||||||
|
*
|
||||||
|
* @return bool true, wenn die Mail uebergeben werden konnte
|
||||||
|
*/
|
||||||
function SendMailMessageSilent($con, $empfaenger, $betreff, $body){
|
function SendMailMessageSilent($con, $empfaenger, $betreff, $body){
|
||||||
|
|
||||||
// LOGIN CONFIG AUSLESEN
|
// LOGIN CONFIG AUSLESEN
|
||||||
$queryconfig = mysqli_query($con, "Select * FROM config");
|
$queryconfig = mysqli_query($con, "Select * FROM config");
|
||||||
$rowconfig = mysqli_fetch_assoc($queryconfig);
|
if($queryconfig === false){
|
||||||
|
error_log("SendMailMessageSilent: config-Tabelle nicht lesbar: " . mysqli_error($con));
|
||||||
if($queryconfig->num_rows == 1){
|
return false;
|
||||||
$row = mysqli_fetch_assoc($queryconfig);
|
|
||||||
$userid = $row["mailserver"];
|
|
||||||
echo $userid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rowconfig = mysqli_fetch_assoc($queryconfig);
|
||||||
|
if($rowconfig === null){
|
||||||
|
error_log("SendMailMessageSilent: kein Datensatz in der Tabelle config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$mailserver = $rowconfig["mailserver"];
|
$mailserver = $rowconfig["mailserver"];
|
||||||
$mailUsername = $rowconfig["mailUsername"];
|
$mailUsername = $rowconfig["mailUsername"];
|
||||||
$mailPassword = $rowconfig["mailPassword"];
|
$mailPassword = $rowconfig["mailPassword"];
|
||||||
@@ -2968,11 +3026,16 @@ function SendMailMessageSilent($con, $empfaenger, $betreff, $body){
|
|||||||
//$mail->Encoding = 'base64';
|
//$mail->Encoding = 'base64';
|
||||||
|
|
||||||
$mail->send();
|
$mail->send();
|
||||||
|
return true;
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
// Nicht nach aussen werfen, aber auch nicht verschweigen.
|
||||||
|
error_log(sprintf(
|
||||||
|
'SendMailMessageSilent: Versand an %s fehlgeschlagen: %s',
|
||||||
|
(string)$empfaenger,
|
||||||
|
$mail->ErrorInfo !== '' ? $mail->ErrorInfo : $e->getMessage()
|
||||||
|
));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-25
@@ -30,31 +30,14 @@ if(isset($_GET['send']) ) {
|
|||||||
$error = "<b>Kein Benutzer gefunden</b>";
|
$error = "<b>Kein Benutzer gefunden</b>";
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$passwortcode = random_string();
|
// Codeerzeugung und Mailtext liegen in sendeAuthentifizierungsMail(),
|
||||||
$statement = $pdo->prepare("UPDATE intern_users SET passwortcode = :passwortcode, passwortcode_time = NOW() WHERE id = :userid");
|
// damit register.php exakt dieselbe Mail verschickt.
|
||||||
$result = $statement->execute(array('passwortcode' => sha1($passwortcode), 'userid' => $user['id']));
|
if(sendeAuthentifizierungsMail($pdo, $user, $organisationsname)) {
|
||||||
|
echo "Ein Link, um Ihr Konto per E-Mail zu authentifizieren, wurde an Ihre E-Mail-Adresse gesendet.";
|
||||||
$empfaenger = $user['email'];
|
$showForm = false;
|
||||||
$betreff = "Authentifizierung für deinen Account auf ". $_SERVER['SERVER_NAME'];
|
} else {
|
||||||
|
$error = "<b>Die E-Mail konnte gerade nicht versendet werden. Bitte versuchen Sie es später noch einmal.</b>";
|
||||||
$url_passwortcode = getSiteURL().'authentifizierung.php?userid='.$user['id'].'&code='.$passwortcode;
|
}
|
||||||
$text = 'Hallo '.$user['vorname'].',<br><br>
|
|
||||||
für die Nutzung des Kontos müssen Sie das Konto per E-Mail authentifizieren. Dazu klicken Sie auf den folgenden Link:<br>
|
|
||||||
'.$url_passwortcode.'
|
|
||||||
<br><br>
|
|
||||||
Nach der Authentifizierung können Sie das Konto vollumfänglich nutzen.<br><br>
|
|
||||||
Haben Sie keine Konto bei uns angelegt, ignorieren Sie diese E-Mail.<br><br>
|
|
||||||
|
|
||||||
Viele Grüße,<br>
|
|
||||||
Ihr ' .$organisationsname . ' Team';
|
|
||||||
|
|
||||||
//echo $text;
|
|
||||||
|
|
||||||
$mailOk = SendMailMessage($pdo, $empfaenger, $betreff ,$text);
|
|
||||||
|
|
||||||
|
|
||||||
echo "Ein Link, um Ihr Konto per E-Mail zu authentifizieren, wurde an deine E-Mail-Adresse gesendet.";
|
|
||||||
$showForm = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ require_once(__DIR__ . "/../inc/functions.inc.php");
|
|||||||
require_once(__DIR__ . "/../inc/functions.impfen.inc.php");
|
require_once(__DIR__ . "/../inc/functions.impfen.inc.php");
|
||||||
require_once(__DIR__ . "/../inc/impfworkflow_notifications.inc.php");
|
require_once(__DIR__ . "/../inc/impfworkflow_notifications.inc.php");
|
||||||
|
|
||||||
ini_set('display_errors', '1');
|
// Fehler protokollieren, aber nicht an Besucher ausgeben.
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
$user = check_intern_user();
|
$user = check_intern_user();
|
||||||
|
|||||||
+20
-4
@@ -47,7 +47,7 @@ if (!empty($_POST['email']) && !empty($_POST['passwort'])) {
|
|||||||
'code' => $codeHash
|
'code' => $codeHash
|
||||||
]);
|
]);
|
||||||
|
|
||||||
SendMailMessageSilent(
|
$mailOk = SendMailMessageSilent(
|
||||||
$con,
|
$con,
|
||||||
$user['email'],
|
$user['email'],
|
||||||
'Ihr Login-Code für Praxis-Creutzburg.de',
|
'Ihr Login-Code für Praxis-Creutzburg.de',
|
||||||
@@ -55,11 +55,27 @@ if (!empty($_POST['email']) && !empty($_POST['passwort'])) {
|
|||||||
Geben Sie diesen Code niemals weiter."
|
Geben Sie diesen Code niemals weiter."
|
||||||
);
|
);
|
||||||
|
|
||||||
header('Location: verify_2fa.php');
|
if ($mailOk) {
|
||||||
exit;
|
header('Location: verify_2fa.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ohne zugestellten Code kommt der Benutzer auf verify_2fa.php nicht
|
||||||
|
// weiter. Statt ihn dort warten zu lassen, den Versuch zuruecknehmen
|
||||||
|
// und es hier sagen. Die Ursache steht im Server-Log.
|
||||||
|
$pdo->prepare("DELETE FROM intern_2fa_codes WHERE user_id = :uid")
|
||||||
|
->execute(['uid' => $user['id']]);
|
||||||
|
unset($_SESSION['2fa_userid']);
|
||||||
|
|
||||||
|
$error_msg = "Der Login-Code konnte gerade nicht per E-Mail versendet werden. "
|
||||||
|
. "Bitte versuchen Sie es in ein paar Minuten erneut oder rufen Sie uns an.";
|
||||||
}
|
}
|
||||||
|
|
||||||
$error_msg = "E-Mail oder Passwort war ungültig";
|
// Nur setzen, wenn oben nicht schon eine genauere Meldung entstanden ist
|
||||||
|
// (z. B. weil der Code nicht versendet werden konnte).
|
||||||
|
if ($error_msg === "") {
|
||||||
|
$error_msg = "E-Mail oder Passwort war ungültig";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ session_start();
|
|||||||
require_once(__DIR__ . "/../inc/config.inc.php");
|
require_once(__DIR__ . "/../inc/config.inc.php");
|
||||||
require_once(__DIR__ . "/../inc/functions.inc.php");
|
require_once(__DIR__ . "/../inc/functions.inc.php");
|
||||||
|
|
||||||
ini_set('display_errors', 1);
|
// Fehler protokollieren, aber nicht an Besucher ausgeben.
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
include("templates/header.inc.php");
|
include("templates/header.inc.php");
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ session_start();
|
|||||||
require_once(__DIR__ . "/../inc/config.inc.php");
|
require_once(__DIR__ . "/../inc/config.inc.php");
|
||||||
require_once(__DIR__ . "/../inc/functions.inc.php");
|
require_once(__DIR__ . "/../inc/functions.inc.php");
|
||||||
|
|
||||||
ini_set('display_errors', 1);
|
// Fehler protokollieren, aber nicht an Besucher ausgeben.
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
include("templates/header.inc.php");
|
include("templates/header.inc.php");
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ ob_start();
|
|||||||
require_once(__DIR__ . "/../inc/config.inc.php");
|
require_once(__DIR__ . "/../inc/config.inc.php");
|
||||||
require_once(__DIR__ . "/../inc/functions.inc.php");
|
require_once(__DIR__ . "/../inc/functions.inc.php");
|
||||||
|
|
||||||
ini_set('display_errors', '1');
|
// Fehler protokollieren, aber nicht an Besucher ausgeben.
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+26
-5
@@ -119,14 +119,35 @@ if(isset($_GET['register'])) {
|
|||||||
|
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
|
||||||
echo 'Du wurdest erfolgreich registriert. <a href="login.php">Zum Login</a>';
|
echo 'Du wurdest erfolgreich registriert. <a href="login.php">Zum Login</a><br>';
|
||||||
$showFormular = false;
|
$showFormular = false;
|
||||||
|
|
||||||
|
// Bisher wurde hier keine Mail verschickt: mailreg blieb 0 und jeder
|
||||||
|
// neue Benutzer landete nach dem Login auf der Aufforderung, die
|
||||||
|
// Authentifizierung selbst anzustossen. Den Link gibt es jetzt sofort.
|
||||||
|
$stmt = $pdo->prepare("SELECT id, vorname, email FROM intern_users WHERE email = :email LIMIT 1");
|
||||||
|
$stmt->execute([':email' => $email]);
|
||||||
|
$neuerUser = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($neuerUser && sendeAuthentifizierungsMail($pdo, $neuerUser, $organisationsname)) {
|
||||||
|
echo 'Wir haben Ihnen eine E-Mail geschickt. Bitte bestätigen Sie darin '
|
||||||
|
. 'Ihre Adresse, damit Sie das Konto vollständig nutzen können.<br>';
|
||||||
|
} else {
|
||||||
|
echo 'Die Bestätigungs-E-Mail konnte gerade nicht versendet werden. '
|
||||||
|
. 'Sie können sie nach dem Login jederzeit erneut anfordern.<br>';
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$pdo->rollBack();
|
// Der Mailversand laeuft nach dem commit(). Ohne diese Pruefung
|
||||||
echo 'Fehler beim Registrieren.<br>';
|
// wuerde ein Fehler dort in rollBack() ohne offene Transaktion
|
||||||
echo ($e->getMessage());
|
// laufen und die Seite mit einem Fatal Error abbrechen.
|
||||||
echo "<br>";
|
if ($pdo->inTransaction()) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
}
|
||||||
|
// Interne Fehlermeldungen gehoeren ins Log, nicht auf die Seite.
|
||||||
|
error_log('register.php: Registrierung fehlgeschlagen: ' . $e->getMessage());
|
||||||
|
echo 'Bei der Registrierung ist ein Fehler aufgetreten. '
|
||||||
|
. 'Bitte versuchen Sie es später noch einmal oder rufen Sie uns an.<br>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ require_once(__DIR__ . '/../inc/config.inc.php');
|
|||||||
require_once(__DIR__ . '/../inc/functions.inc.php');
|
require_once(__DIR__ . '/../inc/functions.inc.php');
|
||||||
require_once(__DIR__ . '/../inc/vacation_absence.inc.php');
|
require_once(__DIR__ . '/../inc/vacation_absence.inc.php');
|
||||||
|
|
||||||
ini_set('display_errors', '1');
|
// Fehler protokollieren, aber nicht an Besucher ausgeben.
|
||||||
ini_set('display_startup_errors', '1');
|
ini_set('display_errors', '0');
|
||||||
|
ini_set('log_errors', '1');
|
||||||
|
ini_set('display_startup_errors', '0');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
if (!function_exists('vacationApiTableHasColumn')) {
|
if (!function_exists('vacationApiTableHasColumn')) {
|
||||||
|
|||||||
Reference in New Issue
Block a user