Unifi-Voucher-Tool/includes/Captcha.php
Claude ce75215498
CAPTCHA für öffentlichen Modus (Rechenaufgabe oder hCaptcha)
- includes/Captcha.php (math self-contained / hcaptcha via siteverify)
- index.php: Verifikation bei anonymer Erstellung + Anzeige in beiden Formularen
- Settings in admin/integrations.php (Modus, Site-Key, Secret)
2026-06-06 05:42:06 +00:00

56 lines
2.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Captcha Schutz der öffentlichen (anonymen) Voucher-Erstellung.
*
* Modi (Setting captcha_mode):
* 'off' deaktiviert
* 'math' selbst-enthaltenes Rechen-Captcha (keine externen Dienste)
* 'hcaptcha' hCaptcha (Setting captcha_site_key / captcha_secret)
*
* Reine PHP-Standardlib + cURL (für hCaptcha-Verifizierung).
*/
class Captcha {
public static function mode($db) {
$m = (string)$db->getSetting('captcha_mode', 'off');
return in_array($m, ['off', 'math', 'hcaptcha'], true) ? $m : 'off';
}
/** Frage für das Math-Captcha erzeugen und Antwort in Session hinterlegen. */
public static function newMathChallenge() {
$a = random_int(1, 9);
$b = random_int(1, 9);
$_SESSION['captcha_answer'] = (string)($a + $b);
return "$a + $b";
}
/** Prüft die Captcha-Antwort des aktuellen Requests. */
public static function verify($db) {
$mode = self::mode($db);
if ($mode === 'off') {
return true;
}
if ($mode === 'math') {
$expected = $_SESSION['captcha_answer'] ?? null;
unset($_SESSION['captcha_answer']); // einmalig
$given = trim((string)($_POST['captcha'] ?? ''));
return $expected !== null && hash_equals((string)$expected, $given);
}
if ($mode === 'hcaptcha') {
$resp = $_POST['h-captcha-response'] ?? '';
if ($resp === '') return false;
$secret = (string)$db->getSetting('captcha_secret', '');
$ch = curl_init('https://hcaptcha.com/siteverify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['secret' => $secret, 'response' => $resp]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 8,
]);
$out = curl_exec($ch);
curl_close($ch);
$data = json_decode((string)$out, true);
return is_array($data) && !empty($data['success']);
}
return true;
}
}