added login rate limit

This commit is contained in:
lakshya chauhan
2022-07-21 17:08:13 +05:30
parent 617f04c975
commit 5fb51e7692
2 changed files with 104 additions and 7 deletions

87
classes/LoginFail.php Normal file
View File

@@ -0,0 +1,87 @@
<?php
/**
* 2010-2022 Webkul.
*
* NOTICE OF LICENSE
*
* All right is reserved,
* Please go through this link for complete license : https://store.webkul.com/license.html
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to newer
* versions in the future. If you wish to customize this module for your
* needs please refer to https://store.webkul.com/customisation-guidelines/ for more information.
*
* @author Webkul IN <support@webkul.com>
* @copyright 2010-2022 Webkul IN
* @license https://store.webkul.com/license.html
*/
class LoginFailCore extends ObjectModel
{
public $id_failed_login;
public $ip_address;
public $email;
public $created_at;
const USERNAME_ATTEMPTS_PER_QUARTER_HOUR = 3;
const IP_ATTEMPTS_QUARTER_HOUR = 12;
const USERNAME_ATTEMPTS_PER_HOUR = 6;
const IP_ATTEMPTS_PER_HOUR = 24;
const QUARTER_HOUR = 60*15;
const HOUR = 60*60;
/**
* @see ObjectModel::$definition
*/
public static $definition = array(
'table' => 'login_fail',
'primary' => 'id_login_fail',
'fields' => array(
'ip_address' => array('type' => self::TYPE_STRING, 'size' => 50),
'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128),
),
);
public function cleanData()
{
$time = (time() - (self::HOUR*2));
Db::getInstance()->execute(
'
DELETE FROM `' . _DB_PREFIX_ . 'login_fail`
WHERE `created_at` < "' . pSQL(date("Y-m-d H:i:s", $time)) . '"'
);
}
public function getUserFailedCount($time, $email=false, $ip_address=false, $attempts)
{
$sql = "SELECT COUNT(id_login_fail) FROM `". _DB_PREFIX_ ."login_fail` WHERE `created_at` > '"
. pSQL(date('Y-m-d H:i:s', $time)) ."'";
if ($email) {
$sql .= " AND `email` = '".pSQL($email)."'";
}
if ($ip_address) {
$sql .= " AND `ip_address` = '".pSQL($ip_address)."'";
}
return Db::getInstance()->getValue($sql) >= $attempts;
}
public function checkLimit($email)
{
$has_error = false;
$minutes_ago = time() - self::QUARTER_HOUR;
$hours_ago = time() - self::HOUR;
$ip_address = Tools::getRemoteAddr();
$has_error = $this->getUserFailedCount($minutes_ago, $email, false, self::USERNAME_ATTEMPTS_PER_QUARTER_HOUR)? true : $has_error;
$has_error = $this->getUserFailedCount($minutes_ago, false, $ip_address, self::IP_ATTEMPTS_QUARTER_HOUR)? true : $has_error;
$has_error = $this->getUserFailedCount($hours_ago, $email, false, self::USERNAME_ATTEMPTS_PER_HOUR)? true : $has_error;
$has_error = $this->getUserFailedCount($hours_ago, false, $ip_address, self::IP_ATTEMPTS_PER_HOUR)? true : $has_error;
return $has_error;
}
}

View File

@@ -249,10 +249,7 @@ class FrontControllerCore extends Controller
$this->context->smarty->assign(Meta::getMetaTags($this->context->language->id, $page_name));
$this->context->smarty->assign('request_uri', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
// Init cookie language
// @TODO This method must be moved into switchLanguage
Tools::setCookieLanguage($this->context->cookie);
$this->displayMaintenancePage();
// If current URL use SSL, set it true (used a lot for module redirect)
if (Tools::usingSecureMode()) {
@@ -277,6 +274,9 @@ class FrontControllerCore extends Controller
}
ob_start();
// Init cookie language
// @TODO This method must be moved into switchLanguage
$protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://';
$useSSL = ((isset($this->ssl) && $this->ssl && Configuration::get('PS_SSL_ENABLED')) || Tools::usingSecureMode()) ? true : false;
$protocol_content = ($useSSL) ? 'https://' : 'http://';
@@ -750,7 +750,7 @@ class FrontControllerCore extends Controller
*/
protected function displayMaintenancePage()
{
if (isset(Context::getContext()->cookie->remote_addr)
if (isset(Context::getContext()->cookie->remote_addr)
&& Context::getContext()->cookie->remote_addr != ip2long(Tools::getRemoteAddr())
) {
$cookie = Context::getContext()->cookie;
@@ -761,7 +761,7 @@ class FrontControllerCore extends Controller
}
}
if (Tools::isSubmit('SubmitLogin')
if (Tools::isSubmit('SubmitLogin')
&& Configuration::get('PS_ALLOW_EMP')
&& !Context::getContext()->cookie->enable_maintenance_view
) {
@@ -769,7 +769,7 @@ class FrontControllerCore extends Controller
$passwd = trim(Tools::getValue('passwd'));
$this->processLogin($email, $passwd);
}
if (!Context::getContext()->cookie->enable_maintenance_view || !Configuration::get('PS_ALLOW_EMP')) {
Context::getContext()->cookie->__unset('enable_maintenance_view');
Context::getContext()->cookie->write();
@@ -777,7 +777,7 @@ class FrontControllerCore extends Controller
$this->maintenance = true;
if (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))) {
header('HTTP/1.1 503 temporarily overloaded');
$this->context->smarty->assign($this->initLogoAndFavicon());
$this->context->smarty->assign(array(
'HOOK_MAINTENANCE' => Hook::exec('displayMaintenance', array()),
@@ -796,6 +796,8 @@ class FrontControllerCore extends Controller
protected function processLogin($email, $passwd)
{
$result = false;
$objLoginFail = new LoginFail;
/* Check fields validity */
if (empty($email)) {
$this->errors[] = Tools::displayError('Email is empty.');
@@ -809,6 +811,10 @@ class FrontControllerCore extends Controller
$this->errors[] = Tools::displayError('Invalid password.');
}
if ($objLoginFail->checkLimit($email)) {
$this->errors[] =Tools::displayError('You have exceeded the limit of login attempts, please try after some time');
}
if (!count($this->errors)) {
// Find employee
$this->context->employee = new Employee();
@@ -829,6 +835,10 @@ class FrontControllerCore extends Controller
}
if (count($this->errors)) {
$this->context->smarty->assign('errors', $this->errors);
$objLoginFail->email = $email;
$objLoginFail->ip_address = Tools::getRemoteAddr();
$objLoginFail->save();
$objLoginFail->cleanData();
} else {
Tools::redirect('index.php');
}