feat(antispam): add server-side contact form spam guard (honeypot, time-trap, rate limit, link cap)
This commit is contained in:
@@ -12,6 +12,7 @@ export default function ContactForm() {
|
||||
const { trackEvent } = useAnalytics();
|
||||
const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
|
||||
const [hasStarted, setHasStarted] = useState(false);
|
||||
const [formLoadedAt] = useState(() => Date.now());
|
||||
|
||||
const handleFocus = (fieldId: string) => {
|
||||
// Initial form start
|
||||
@@ -152,6 +153,8 @@ export default function ContactForm() {
|
||||
style={{ display: 'none' }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{/* Anti-spam time-trap: server rejects submissions faster than a human could fill the form */}
|
||||
<input type="hidden" name="form_loaded_at" value={formLoadedAt} />
|
||||
<div className="space-y-1 md:space-y-2">
|
||||
<Label htmlFor="contact-name">{t('form.name')}</Label>
|
||||
<Input
|
||||
|
||||
@@ -18,6 +18,7 @@ export default function RequestQuoteForm({ productName }: RequestQuoteFormProps)
|
||||
const [request, setRequest] = useState('');
|
||||
const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
|
||||
const [hasStarted, setHasStarted] = useState(false);
|
||||
const [formLoadedAt] = useState(() => Date.now());
|
||||
|
||||
const handleFocus = (fieldId: string) => {
|
||||
// Initial form start
|
||||
@@ -172,8 +173,10 @@ export default function RequestQuoteForm({ productName }: RequestQuoteFormProps)
|
||||
tabIndex={-1}
|
||||
autoComplete="off"
|
||||
style={{ display: 'none' }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{/* Anti-spam time-trap: server rejects submissions faster than a human could fill the form */}
|
||||
<input type="hidden" name="form_loaded_at" value={formLoadedAt} />
|
||||
|
||||
<div className="space-y-2 !mt-0">
|
||||
<div className="space-y-1 !mt-0">
|
||||
|
||||
@@ -7,6 +7,7 @@ import { sendContactFormAction } from '@/app/actions/contact';
|
||||
|
||||
export function ContactForm() {
|
||||
const [status, setStatus] = React.useState<'idle' | 'loading' | 'success' | 'error'>('idle');
|
||||
const [formLoadedAt] = React.useState(() => Date.now());
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
@@ -132,6 +133,7 @@ export function ContactForm() {
|
||||
</div>
|
||||
|
||||
<input type="text" name="company_website" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
|
||||
<input type="hidden" name="form_loaded_at" value={formLoadedAt} />
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
Reference in New Issue
Block a user