Fixes errors in ratelimiter
parent
4182ba6c1b
commit
487c23da3e
|
@ -123,7 +123,20 @@ class RateLimiter {
|
|||
*/
|
||||
public function isIpBlacklisted($ip) {
|
||||
// First check if IP is explicitly blacklisted or in a blacklisted range
|
||||
$stmt = $this->db->prepare("SELECT ip_address, is_network, expiry_time FROM {$this->blacklistTable}");
|
||||
$stmt = $this->db->prepare("SELECT ip_address, is_network, expiry_time FROM {$this->blacklistTable} WHERE ip_address = ?");
|
||||
$stmt->execute([$ip]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row) {
|
||||
// Skip expired entries
|
||||
if ($row['expiry_time'] !== null && strtotime($row['expiry_time']) < time()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check network ranges
|
||||
$stmt = $this->db->prepare("SELECT ip_address, expiry_time FROM {$this->blacklistTable} WHERE is_network = 1");
|
||||
$stmt->execute();
|
||||
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
|
@ -132,14 +145,8 @@ class RateLimiter {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($row['is_network']) {
|
||||
if ($this->ipInRange($ip, $row['ip_address'])) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ($ip === $row['ip_address']) {
|
||||
return true;
|
||||
}
|
||||
if ($this->ipInRange($ip, $row['ip_address'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,6 +314,7 @@ class RateLimiter {
|
|||
|
||||
// Remove the IP
|
||||
$stmt = $this->db->prepare("DELETE FROM {$this->blacklistTable} WHERE ip_address = ?");
|
||||
|
||||
$result = $stmt->execute([$ip]);
|
||||
|
||||
if ($result && $ipDetails) {
|
||||
|
@ -495,12 +503,12 @@ class RateLimiter {
|
|||
// Get limit based on endpoint type and user role
|
||||
$limit = $this->getPageLimitForEndpoint($endpoint, $userId);
|
||||
|
||||
// Count recent requests
|
||||
// Count recent requests, including this one
|
||||
$sql = "SELECT COUNT(*) as request_count
|
||||
FROM {$this->pagesRatelimitTable}
|
||||
WHERE ip_address = :ip
|
||||
AND endpoint = :endpoint
|
||||
AND request_time > DATETIME('now', '-1 minute')";
|
||||
AND request_time >= DATETIME('now', '-1 minute')";
|
||||
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->execute([
|
||||
|
|
|
@ -12,7 +12,7 @@ require_once __DIR__ . '/../classes/ratelimiter.php';
|
|||
*/
|
||||
function checkRateLimit($database, $endpoint, $userId = null) {
|
||||
$isTest = defined('PHPUNIT_RUNNING');
|
||||
$rateLimiter = new RateLimiter($database['db']);
|
||||
$rateLimiter = new RateLimiter($database);
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// Check if request is allowed
|
||||
|
|
|
@ -19,11 +19,11 @@ unset($error);
|
|||
try {
|
||||
|
||||
// connect to database
|
||||
$dbWeb = connectDB($config);
|
||||
$dbWeb = connectDB($config)['db'];
|
||||
|
||||
// Initialize RateLimiter
|
||||
require_once '../app/classes/ratelimiter.php';
|
||||
$rateLimiter = new RateLimiter($dbWeb['db']);
|
||||
$rateLimiter = new RateLimiter($dbWeb);
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
try {
|
||||
|
@ -54,8 +54,8 @@ try {
|
|||
throw new Exception("Invalid input: " . implode(", ", $errors));
|
||||
}
|
||||
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
$username = $formData['username'];
|
||||
$password = $formData['password'];
|
||||
|
||||
// Check if IP is blacklisted
|
||||
if ($rateLimiter->isIpBlacklisted($user_IP)) {
|
||||
|
@ -73,7 +73,7 @@ try {
|
|||
// login successful
|
||||
if ( $userObject->login($username, $password) ) {
|
||||
// if remember_me is checked, max out the session
|
||||
if (isset($_POST['remember_me'])) {
|
||||
if (isset($formData['remember_me'])) {
|
||||
// 30*24*60*60 = 30 days
|
||||
$cookie_lifetime = 30 * 24 * 60 * 60;
|
||||
$setcookie_lifetime = time() + 30 * 24 * 60 * 60;
|
||||
|
@ -119,7 +119,7 @@ try {
|
|||
$logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user');
|
||||
|
||||
// Set success message and redirect
|
||||
Feedback::flash('LOGIN', 'LOGIN_SUCCESS', null, true);
|
||||
Feedback::flash('LOGIN', 'LOGIN_SUCCESS');
|
||||
header('Location: ' . htmlspecialchars($app_root));
|
||||
exit();
|
||||
} else {
|
||||
|
@ -140,7 +140,7 @@ try {
|
|||
|
||||
// Show configured login message if any
|
||||
if (!empty($config['login_message'])) {
|
||||
echo Feedback::render('NOTICE', 'DEFAULT', $config['login_message'], false, false, false);
|
||||
echo Feedback::render('NOTICE', 'DEFAULT', $config['login_message'], false);
|
||||
}
|
||||
|
||||
// Get any new feedback messages
|
||||
|
|
|
@ -14,7 +14,7 @@ if ($config['registration_enabled'] == true) {
|
|||
try {
|
||||
|
||||
// connect to database
|
||||
$dbWeb = connectDB($config);
|
||||
$dbWeb = connectDB($config)['db'];
|
||||
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ require_once '../app/helpers/security.php';
|
|||
$security = SecurityHelper::getInstance();
|
||||
|
||||
// Verify CSRF token for POST requests
|
||||
verifyCsrfToken();
|
||||
applyCsrfMiddleware();
|
||||
|
||||
// Initialize feedback message system
|
||||
require_once '../app/classes/feedback.php';
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require_once dirname(__DIR__, 3) . '/app/classes/database.php';
|
||||
require_once dirname(__DIR__, 3) . '/app/classes/ratelimiter.php';
|
||||
require_once dirname(__DIR__, 3) . '/app/classes/log.php';
|
||||
require_once dirname(__DIR__, 3) . '/app/includes/rate_limit_middleware.php';
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -75,7 +76,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
{
|
||||
// Test multiple requests
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
|
||||
if ($i <= 5) {
|
||||
// First 5 requests should pass
|
||||
|
@ -91,7 +92,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
{
|
||||
// Test AJAX request bypass
|
||||
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
|
@ -99,14 +100,14 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
{
|
||||
// Use up the rate limit
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
checkRateLimit(['db' => $this->db], '/login');
|
||||
checkRateLimit($this->db, '/login');
|
||||
}
|
||||
|
||||
// Wait for rate limit to reset (use a short window for testing)
|
||||
sleep(2);
|
||||
|
||||
// Should be able to make request again
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
|
@ -114,11 +115,11 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
{
|
||||
// Use up rate limit for login
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
checkRateLimit(['db' => $this->db], '/login');
|
||||
checkRateLimit($this->db, '/login');
|
||||
}
|
||||
|
||||
// Should still be able to access different endpoint
|
||||
$result = checkRateLimit(['db' => $this->db], '/dashboard');
|
||||
$result = checkRateLimit($this->db, '/dashboard');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
|
@ -127,12 +128,12 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
// Use up rate limit for first IP
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
checkRateLimit(['db' => $this->db], '/login');
|
||||
checkRateLimit($this->db, '/login');
|
||||
}
|
||||
|
||||
// Different IP should not be affected
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
|
@ -146,7 +147,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
|
||||
// Should be able to make more requests than limit
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +161,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
);
|
||||
|
||||
// Should be blocked immediately
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
{
|
||||
// Use up some of the rate limit
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
checkRateLimit(['db' => $this->db], '/login');
|
||||
checkRateLimit($this->db, '/login');
|
||||
}
|
||||
|
||||
// Destroy and restart session
|
||||
|
@ -176,7 +177,7 @@ class RateLimitMiddlewareTest extends TestCase
|
|||
//session_start();
|
||||
|
||||
// Should still count previous requests
|
||||
$result = checkRateLimit(['db' => $this->db], '/login');
|
||||
$result = checkRateLimit($this->db, '/login');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue