Skip to content

Commit

Permalink
[FEATURE] Added configurable delay for response calculation
Browse files Browse the repository at this point in the history
Refs #1
  • Loading branch information
derhansen committed Jul 3, 2022
1 parent 7d12c29 commit 753e765
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 7 deletions.
13 changes: 12 additions & 1 deletion Classes/Hooks/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator;
Expand All @@ -28,14 +29,24 @@ public function afterInitializeCurrentPage(FormRuntime $runtime, ?Page $currentP
{
$pageObject = $currentPage ?? $page;

// Set delay for initial form (no delay for re-submission of form)
$extensionSettings = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('form_crshield');
$delay = $runtime->getFormSession() === null ? (int)($extensionSettings['crJavaScriptDelay'] ?? 0) : 0;

if ($pageObject) {
$pageMaxLifetime = $this->getPageMaxLifetime($runtime->getRequest());
$expirationTime = time() + $pageMaxLifetime;
$challenge = $expirationTime . '|' . GeneralUtility::hmac($expirationTime, $runtime->getIdentifier());

$newElement = $pageObject->createElement(self::FIELD_ID, 'Hidden');
$newElement->addValidator(new NotEmptyValidator());
$newElement->setProperty('fluidAdditionalAttributes', ['data-cr-challenge' => base64_encode($challenge)]);
$newElement->setProperty(
'fluidAdditionalAttributes',
[
'data-cr-challenge' => base64_encode($challenge),
'data-cr-delay' => $delay,
]
);
}

return $currentPage;
Expand Down
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,35 @@ Form challenge/response spam shield
Form challenge/response spam shield is a TYPO3 extension to prevent automated form submissions
in TYPO3 form extension.

### How does it work?
## How does it work?

Form challenge/response spam shield adds a hidden input field to every form generated by the TYPO3 form
extension. The input field contains a data-attribute with a challenge. The included JavaScript will
use the challenge to calculate an expected response which will be checked on every form submission.
If the expected response is not submitted, validation for the hidden input field is considered as
failed and no email will be sent.

### Requirements
In order to make automatic form submissions harder for spambots with active JavaScript, a configurable
delay for the JavaScript response calculation can be defined in the extension settings (default value: 3 seconds).

## Requirements

The extension uses JavaScript to calculate the expected response, so if JavaScript is disabled on client
side, form submission will not be possible.

A modern webbrowser is required to run the JavaScript. Internet Explorer < 11 is not supported.

### Installation
## Installation

Just install the extension on your TYPO3 website using composer or the TYPO3 extension manager.
No further configuration is required.

### Logging
## Settings

It is possible to configure the delay in seconds for the JavaScript response calculation. This can be
done in the extensions settings. The default value is 3 seconds.

## Logging

In order to log failed requests, it is possible to use a dedicated logfile like shown below:

Expand Down
6 changes: 5 additions & 1 deletion Resources/Public/JavaScript/FormCrShield.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ document.addEventListener('DOMContentLoaded', function () {
elementsArray.forEach(element => {
let challengeString = atob(element.getAttribute('data-cr-challenge'));
let [exp,challenge] = challengeString.split('|');
let delay = element.dataset.crDelay;

// ROT13 the challenge - source: https://stackoverflow.com/a/617685/1744743
let response = challenge.replace(/[a-zA-Z]/g, function (c) {
return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
});

element.value = btoa(exp + '|' + response);
// Set calculated response after defined amount of seconds
setTimeout(() => {
element.value = btoa(exp + '|' + response)
}, delay * 1000)
});
});
4 changes: 4 additions & 0 deletions ext_conf_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# settings
###########################
# cat=settings/enable/10; type=integer; label=Delay in seconds when response calculation is set using JavaScript
crJavaScriptDelay = 3
2 changes: 1 addition & 1 deletion ext_emconf.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
'uploadfolder' => '0',
'createDirs' => '',
'clearCacheOnLoad' => 1,
'version' => '1.0.0',
'version' => '1.1.0',
'constraints' => [
'depends' => [
'typo3' => '11.5.0-11.5.99',
Expand Down

0 comments on commit 753e765

Please sign in to comment.