Apply firewall security on BaseForm::validateForm

modified:   core/lib/Thelia/Controller/BaseController.php
	modified:   core/lib/Thelia/Form/AddressCreateForm.php
	new file:   core/lib/Thelia/Form/FirewallForm.php
	modified:   core/lib/Thelia/Model/FormFirewall.php
	modified:   setup/insert.sql
This commit is contained in:
lovenunu
2014-07-14 20:58:44 +02:00
committed by Benjamin Perche
parent b42ff568e0
commit 978f15357c
5 changed files with 126 additions and 2 deletions

View File

@@ -25,6 +25,7 @@ use Symfony\Component\Routing\Router;
use Thelia\Core\Template\TemplateHelper; use Thelia\Core\Template\TemplateHelper;
use Thelia\Core\Translation\Translator; use Thelia\Core\Translation\Translator;
use Thelia\Form\FirewallForm;
use Thelia\Model\OrderQuery; use Thelia\Model\OrderQuery;
use Thelia\Tools\Redirect; use Thelia\Tools\Redirect;
@@ -200,6 +201,14 @@ abstract class BaseController extends ContainerAware
$form->bind($aBaseForm->getRequest()); $form->bind($aBaseForm->getRequest());
if ($form->isValid()) { if ($form->isValid()) {
if ($aBaseForm instanceof FirewallForm && !$aBaseForm->isFirewallOk()) {
throw new FormValidationException(
$this->getTranslator()->trans(
"You have too much sent this form. Please wait before trying again."
)
);
}
return $form; return $form;
} else { } else {
$errorMessage = null; $errorMessage = null;

View File

@@ -21,7 +21,7 @@ use Thelia\Core\Translation\Translator;
* @package Thelia\Form * @package Thelia\Form
* @author Manuel Raynaud <mraynaud@openstudio.fr> * @author Manuel Raynaud <mraynaud@openstudio.fr>
*/ */
class AddressCreateForm extends BaseForm class AddressCreateForm extends FirewallForm
{ {
/** /**

View File

@@ -0,0 +1,96 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Form;
use Symfony\Component\HttpFoundation\Request;
use Thelia\Model\ConfigQuery;
use Thelia\Model\FormFirewall;
use Thelia\Model\FormFirewallQuery;
/**
* Class FirewallForm
* @package Thelia\Form
* @author Benjamin Perche <bperche@openstudio.fr>
*/
abstract class FirewallForm extends BaseForm
{
/** @var \Thelia\Model\FormFirewall */
protected static $cachedInstance;
public function __construct(Request $request, $type = "form", $data = array(), $options = array())
{
parent::__construct($request, $type, $data, $options);
static::$cachedInstance = FormFirewallQuery::create()
->filterByFormName($this->getName())
->filterByIpAddress($this->request->getClientIp())
->findOne()
;
}
public function isFirewallOk()
{
if (null !== $firewallRow = &static::$cachedInstance) {
/** @var \DateTime $lastRequestDateTime */
$lastRequestDateTime = $firewallRow->getUpdatedAt();
$lastRequestTimestamp = $lastRequestDateTime->getTimestamp();
/**
* Get the last request execution time in hour.
*/
$lastRequest = (time() - $lastRequestTimestamp) / 3600;
if ($lastRequest > $this->getConfigTime()) {
$firewallRow->resetAttempts();
}
if ($firewallRow->getAttempts() <= $this->getConfigAttempts()) {
$firewallRow->incrementAttempts();
} else {
/** Set updated_at at NOW() */
$firewallRow->save();
return false;
}
} else {
$firewallRow = (new FormFirewall())
->setIpAddress($this->request->getClientIp())
->setFormName($this->getName())
;
$firewallRow->save();
static::$cachedInstance = $firewallRow;
}
return true;
}
/**
* @return int
*
* The time (in hours) to wait if the attempts have been exceeded
*/
public function getConfigTime()
{
return ConfigQuery::read("form_firewall_time_to_wait", 1);
}
/**
* @return int
*
* The number of allowed attempts
*/
public function getConfigAttempts()
{
return ConfigQuery::read("form_firewall_attempts", 2);
}
}

View File

@@ -6,5 +6,21 @@ use Thelia\Model\Base\FormFirewall as BaseFormFirewall;
class FormFirewall extends BaseFormFirewall class FormFirewall extends BaseFormFirewall
{ {
public function resetAttempts()
{
$this->setAttempts(1)->save();
return $this;
}
public function incrementAttempts()
{
$this->setAttempts(
$this->getAttempts() + 1
);
$this->save();
return $this;
}
} }

View File

@@ -51,7 +51,10 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat
('front_cart_country_cookie_name','fcccn', 1, 1, NOW(), NOW()), ('front_cart_country_cookie_name','fcccn', 1, 1, NOW(), NOW()),
('front_cart_country_cookie_expires','2592000', 1, 1, NOW(), NOW()), ('front_cart_country_cookie_expires','2592000', 1, 1, NOW(), NOW()),
('sitemap_ttl','7200', 1, 1, NOW(), NOW()), ('sitemap_ttl','7200', 1, 1, NOW(), NOW()),
('feed_ttl','7200', 1, 1, NOW(), NOW()); ('feed_ttl','7200', 1, 1, NOW(), NOW()),
('form_firewall_time_to_wait', '1', 1, 1, NOW(), NOW()),
('form_firewall_attempts', '3', 1, 1, NOW(), NOW());
INSERT INTO `config_i18n` (`id`, `locale`, `title`, `description`, `chapo`, `postscriptum`) VALUES INSERT INTO `config_i18n` (`id`, `locale`, `title`, `description`, `chapo`, `postscriptum`) VALUES