I had a bot attack on all of my forms recently. The knee-jerk reaction from everyone was to add captcha to all the forms. But I hate them.
So I created a cool-down hook to slow the bots down. Most people do not submit form twice so quickly.
It is working for me, but I was wondering if anyone else could use it, and or did I miss a feature.
The prehook creates a session with a timestamp. The hook compares it to the time and a delay.
FormItWaitForItPreHook
<?php
$waitSessionName = $modx->getOption('waitSessionName', $formit->config, 'waitSession');
if (!isset($_SESSION[$waitSessionName])) {
$_SESSION[$waitSessionName] = time();
}
// debug
// $hook->setValue('session', $_SESSION[$waitSessionName] . ' - ' . time());
return true;
FormItWaitForIt
<?php
$waitSessionName = $modx->getOption('waitSessionName', $formit->config, 'waitSession');
$delay = $modx->getOption('delay', $formit->config, 15);
$delayPenalty = $modx->getOption('delayPenalty', $formit->config, 30);
$delayTimer = ($_SESSION[$waitSessionName] - time()) + $delayPenalty;
$s = $delayTimer%60;
$dTm = floor(($delayTimer % 3600) / 60);
$dTh = floor(($delayTimer % 86400) / 3600);
$m = $dTm>0?$dTm.' minute'.($dTm>1?'s':''):'';
$h = $dTh>0?$dTh.' hour'.($dTh>1?'s':''):'';
$timeRemaining = "$h $m $s seconds" . ' ' . $_SESSION[$waitSessionName] . ' ' . $delayTimer;
$waitErrorMsg = $modx->getOption('waitErrorMsg', $formit->config, 'Too soon, please wait [[!+timeRemaining]]');
if ($_SESSION[$waitSessionName]+$delay <= time()){
$_SESSION[$waitSessionName] = time();
return true;
} else {
$_SESSION[$waitSessionName] = time() + $delayTimer;
$modx->log(modX::LOG_LEVEL_INFO, $_SESSION[$waitSessionName]);
$hook->addError('waitError',$waitErrorMsg);
$modx->setPlaceholder('timeRemaining', $timeRemaining);
return false;
}
Test Form
[[!FormIt?
&preHooks=`FormItWaitForItPreHook`
&hooks=`FormItWaitForIt,redirect`
&emailTpl=`MyEmailChunk`
&emailTo=`[email protected]`
&redirectTo=`1`
]]
<h1>Session Form</h1>
<span class="errors">[[!+fi.error.waitError]]</span>
<form action="[[~[[*id]]]]" method="post" class="form">
<div class="form-row">
<label for="session">Session</label>
<input type="text" name="session" size="50" autocomplete="off" class="form-field" value="[[!+fi.session]]"/>
</div>
<button type="submit" class="submit-button">Submit</button>
</form>