new: [flood protection] behaviour added

simple expiration system to allow flood protections to be added to any functionality
cli-modification-summary
iglocska 2022-02-07 02:01:59 +01:00
parent d1cdbda972
commit e6643365d2
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
3 changed files with 82 additions and 0 deletions

View File

@ -41,6 +41,7 @@ class AppController extends Controller
public $restResponsePayload = null;
public $user = null;
public $breadcrumb = [];
public $request_ip = null;
/**
* Initialization hook method.
@ -83,6 +84,7 @@ class AppController extends Controller
Configure::write('DebugKit.forceEnable', true);
}
$this->loadComponent('CustomPagination');
$this->loadComponent('FloodProtection');
/*
* Enable the following component for recommended CakePHP form protection settings.
* 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)
{
//$this->request_ip = Configure::read('')
$this->loadModel('Users');
$this->Users->checkForNewInstance();
$this->authApiUser();

View File

@ -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()]);
}
}

View File

@ -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;
}
}