feat: Math-CAPTCHA (serverseitig, kein externer Dienst) – v1.5.0
- kgv_cf_generate_captcha(): Rechenaufgabe (+/-/×) mit WordPress-Transient - kgv_cf_verify_captcha(): serverseitige Prüfung + einmaliger Token-Verbrauch - Formular: CAPTCHA-Feld mit verstecktem Token - Submit-Handler: Abweisung bei falscher/abgelaufener Antwort - CSS: CAPTCHA-Feld gestylt - Version 1.4.7 → 1.5.0
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Plugin Name: KGV Kontakt Form
|
||||
* Description: Kontaktformular mit Nachrichtenbereich, Kategorien, Routing je Kategorie, Datenschutz-Checkbox, gelesen/ungelesen, Mehrfach-E-Mail und Rollenfreigabe für Kontaktanfragen.
|
||||
* Version: 1.4.7
|
||||
* Version: 1.5.0
|
||||
* Author: Ronny Grobel
|
||||
* Author URI: https://apex-project.de/
|
||||
* Plugin URI: https://wordpress.apex-project.de/
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
define('KGV_CF_VERSION', '1.4.7');
|
||||
define('KGV_CF_VERSION', '1.5.0');
|
||||
define('KGV_CF_VIEW_CAP', 'kgv_view_contact_requests');
|
||||
define('KGV_CF_MANAGE_CAP', 'manage_options');
|
||||
|
||||
@@ -110,6 +110,55 @@ function kgv_cf_run_schema_update() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- CAPTCHA (serverseitig, kein externer Dienst) ---
|
||||
|
||||
function kgv_cf_generate_captcha() {
|
||||
$a = wp_rand(1, 12);
|
||||
$b = wp_rand(1, 12);
|
||||
$ops = ['+', '-', '×'];
|
||||
$op = $ops[array_rand($ops)];
|
||||
|
||||
switch ($op) {
|
||||
case '-':
|
||||
if ($b > $a) { [$a, $b] = [$b, $a]; }
|
||||
$answer = $a - $b;
|
||||
break;
|
||||
case '×':
|
||||
$a = wp_rand(1, 9);
|
||||
$b = wp_rand(1, 9);
|
||||
$answer = $a * $b;
|
||||
break;
|
||||
default:
|
||||
$answer = $a + $b;
|
||||
}
|
||||
|
||||
$token = bin2hex(random_bytes(16));
|
||||
set_transient('kgv_cf_cap_' . $token, (string) $answer, HOUR_IN_SECONDS);
|
||||
|
||||
return [
|
||||
'token' => $token,
|
||||
'question' => sprintf('Sicherheitsfrage: Wie viel ist %d %s %d?', $a, $op, $b),
|
||||
];
|
||||
}
|
||||
|
||||
function kgv_cf_verify_captcha($token, $given) {
|
||||
if (empty($token) || !ctype_xdigit($token) || strlen($token) !== 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key = 'kgv_cf_cap_' . sanitize_text_field($token);
|
||||
$stored = get_transient($key);
|
||||
delete_transient($key);
|
||||
|
||||
if ($stored === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return trim((string) $given) === $stored;
|
||||
}
|
||||
|
||||
// --- Ende CAPTCHA ---
|
||||
|
||||
function kgv_cf_enqueue_assets() {
|
||||
wp_enqueue_style(
|
||||
'kgv-contact-form-style',
|
||||
@@ -336,6 +385,15 @@ function kgv_cf_render_form() {
|
||||
|
||||
<input type="text" name="kgv_hp" value="" autocomplete="off" tabindex="-1" class="kgv-cf-hp">
|
||||
|
||||
<?php
|
||||
$captcha = kgv_cf_generate_captcha();
|
||||
?>
|
||||
<p class="kgv-cf-field kgv-cf-captcha">
|
||||
<label for="kgv_captcha_answer"><?php echo esc_html($captcha['question']); ?> *</label>
|
||||
<input type="text" id="kgv_captcha_answer" name="kgv_captcha_answer" inputmode="numeric" pattern="-?[0-9]+" autocomplete="off" required>
|
||||
<input type="hidden" name="kgv_captcha_token" value="<?php echo esc_attr($captcha['token']); ?>">
|
||||
</p>
|
||||
|
||||
<?php wp_nonce_field('kgv_contact_form_submit', 'kgv_nonce'); ?>
|
||||
|
||||
<p class="kgv-cf-submit">
|
||||
@@ -360,6 +418,13 @@ function kgv_cf_handle_form_submit() {
|
||||
return;
|
||||
}
|
||||
|
||||
$captcha_token = isset($_POST['kgv_captcha_token']) ? sanitize_text_field(wp_unslash($_POST['kgv_captcha_token'])) : '';
|
||||
$captcha_answer = isset($_POST['kgv_captcha_answer']) ? sanitize_text_field(wp_unslash($_POST['kgv_captcha_answer'])) : '';
|
||||
|
||||
if (!kgv_cf_verify_captcha($captcha_token, $captcha_answer)) {
|
||||
kgv_cf_redirect_with_flag('kgv_error', '1');
|
||||
}
|
||||
|
||||
$name = sanitize_text_field($_POST['kgv_name'] ?? '');
|
||||
$email = sanitize_email($_POST['kgv_email'] ?? '');
|
||||
$category_id = absint($_POST['kgv_category'] ?? 0);
|
||||
|
||||
Reference in New Issue
Block a user