new: [flood protection] behaviour added
simple expiration system to allow flood protections to be added to any functionalitycli-modification-summary
parent
d1cdbda972
commit
e6643365d2
|
@ -41,6 +41,7 @@ class AppController extends Controller
|
||||||
public $restResponsePayload = null;
|
public $restResponsePayload = null;
|
||||||
public $user = null;
|
public $user = null;
|
||||||
public $breadcrumb = [];
|
public $breadcrumb = [];
|
||||||
|
public $request_ip = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization hook method.
|
* Initialization hook method.
|
||||||
|
@ -83,6 +84,7 @@ class AppController extends Controller
|
||||||
Configure::write('DebugKit.forceEnable', true);
|
Configure::write('DebugKit.forceEnable', true);
|
||||||
}
|
}
|
||||||
$this->loadComponent('CustomPagination');
|
$this->loadComponent('CustomPagination');
|
||||||
|
$this->loadComponent('FloodProtection');
|
||||||
/*
|
/*
|
||||||
* Enable the following component for recommended CakePHP form protection settings.
|
* Enable the following component for recommended CakePHP form protection settings.
|
||||||
* see https://book.cakephp.org/4/en/controllers/components/form-protection.html
|
* see https://book.cakephp.org/4/en/controllers/components/form-protection.html
|
||||||
|
@ -92,6 +94,7 @@ class AppController extends Controller
|
||||||
|
|
||||||
public function beforeFilter(EventInterface $event)
|
public function beforeFilter(EventInterface $event)
|
||||||
{
|
{
|
||||||
|
//$this->request_ip = Configure::read('')
|
||||||
$this->loadModel('Users');
|
$this->loadModel('Users');
|
||||||
$this->Users->checkForNewInstance();
|
$this->Users->checkForNewInstance();
|
||||||
$this->authApiUser();
|
$this->authApiUser();
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller\Component;
|
||||||
|
|
||||||
|
use Cake\Controller\Component;
|
||||||
|
use App\Model\Entity\User;
|
||||||
|
use App\Http\Exception\TooManyRequestsException;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
use Cake\Core\Configure;
|
||||||
|
use Cake\Core\Configure\Engine\PhpConfig;
|
||||||
|
|
||||||
|
class FloodProtectionComponent extends Component
|
||||||
|
{
|
||||||
|
private $remote_ip = null;
|
||||||
|
private $FloodProtections = null;
|
||||||
|
|
||||||
|
public function initialize(array $config): void
|
||||||
|
{
|
||||||
|
$ip_source = Configure::check('security.logging.ip_source') ? Configure::read('security.logging.ip_source') : 'REMOTE_ADDR';
|
||||||
|
$this->remote_ip = $_SERVER[$ip_source];
|
||||||
|
$temp = explode(PHP_EOL, $_SERVER[$ip_source]);
|
||||||
|
if (count($temp) > 1) {
|
||||||
|
$this->remote_ip = $temp[0];
|
||||||
|
}
|
||||||
|
$this->FloodProtections = TableRegistry::getTableLocator()->get('FloodProtections');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function check(string $action, int $limit = 5, int $expiration_time = 300): bool
|
||||||
|
{
|
||||||
|
$results = $this->FloodProtections->find('all')->where(['request_action' => $action, 'remote_ip' => $this->remote_ip, 'expiration' > time()])->toList();
|
||||||
|
if (count($results) >= $limit) {
|
||||||
|
throw new TooManyRequestsException(__('Too many {0} requests have been issued ({1} requests allowed ever {2} seconds)', [$action, $limit, $expiration_time]));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(string $action, int $expiration_time = 300): bool
|
||||||
|
{
|
||||||
|
$entry = $this->FloodProtections->newEmptyEntity();
|
||||||
|
$entry->expiration = time() + $expiration_time;
|
||||||
|
$entry->remote_ip = $this->remote_ip;
|
||||||
|
$entry->request_action = $action;
|
||||||
|
return (bool)$this->FloodProtections->save($entry);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkAndSet(string $action, int $limit = 5, int $expiration_time = 300): bool
|
||||||
|
{
|
||||||
|
$result = $this->check($action, $limit, $expiration_time);
|
||||||
|
$this->set($action, $expiration_time);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cleanup(): void
|
||||||
|
{
|
||||||
|
$this->FloodProtection->deleteAll(['expiration' < time()]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Model\Table;
|
||||||
|
|
||||||
|
use App\Model\Table\AppTable;
|
||||||
|
use Cake\ORM\Table;
|
||||||
|
use Cake\Validation\Validator;
|
||||||
|
|
||||||
|
class FloodProtectionsTable extends AppTable
|
||||||
|
{
|
||||||
|
public function initialize(array $config): void
|
||||||
|
{
|
||||||
|
parent::initialize($config);
|
||||||
|
$this->setDisplayField('request_ip');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validationDefault(Validator $validator): Validator
|
||||||
|
{
|
||||||
|
return $validator;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue