feat: add honeypot and time-trap bot protection

This commit is contained in:
Chneemann 2026-07-25 08:13:41 +02:00
parent 92812bc70c
commit 6e2c6644df
2 changed files with 39 additions and 1 deletions

View file

@ -14,6 +14,12 @@ switch ($_SERVER['REQUEST_METHOD']) {
$json = file_get_contents('php://input');
$params = json_decode($json);
// Honeypot check
if (!empty($params->website)) {
http_response_code(200);
exit;
}
// Extract values
$email = $params->email;
$name = $params->name;

View file

@ -6,14 +6,30 @@ export default function Contact() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const [honeypot, setHoneypot] = useState("");
const [submitted, setSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [formLoadTime] = useState(Date.now());
const handleSubmit = async (e: React.SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
// Bot check
const timeTaken = (Date.now() - formLoadTime) / 1000;
if (timeTaken < 3) {
setSubmitted(true);
return;
}
if (honeypot !== "") {
setSubmitted(true);
return;
}
setLoading(true);
setError(false);
@ -23,7 +39,7 @@ export default function Contact() {
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name, email, message }),
body: JSON.stringify({ name, email, message, honeypot }),
});
if (response.ok) {
@ -31,6 +47,7 @@ export default function Contact() {
setName("");
setEmail("");
setMessage("");
setHoneypot("");
} else {
setError(true);
}
@ -122,6 +139,21 @@ export default function Contact() {
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-4">
<div className="hidden" aria-hidden="true">
<label className="block text-xs mb-1.5" htmlFor="website">
Website
</label>
<input
type="text"
id="website_hp"
name="website_hp"
tabIndex={-1}
autoComplete="off"
value={honeypot}
onChange={(e) => setHoneypot(e.target.value)}
/>
</div>
<div>
<label className="block text-xs mb-1.5" htmlFor="name">
Name