How JekCMS tracks failed login attempts and automatically blocks abusive IPs to stop brute force attacks — no Redis, memcached, or external dependency required.
Why This Matters
Credential-stuffing tools can fire hundreds of login attempts per minute against any publicly accessible endpoint. An attacker with a leaked username/password list can automate POST requests to /admin/login.php faster than any human could type. Without protection, that's a direct line to your database taking a beating from authentication queries, and every attempt is a shot at guessing correctly.
jekcms handles this at the login layer, not as an optional plugin.
How jekcms Actually Tracks Login Attempts
Every login attempt — successful or not — is recorded in a login_attempts table. When failures from a given IP cross a threshold, SecurityHelper::blockIp() adds that IP to a blocked_ips table, and subsequent requests from that IP are rejected before they ever reach the password check. This is a database-backed mechanism, not a file-based rate limiter with per-key cache files — which matters in practice because it works identically whether you're on shared hosting or a multi-server setup, without needing a shared filesystem or an external cache like Redis.
// admin/login.php (simplified)
db()->insert('login_attempts', [
'ip' => $ip,
'username'=> $username,
'success' => $success ? 1 : 0,
]);
if (!$success) {
$recentFailures = db()->fetch(
"SELECT COUNT(*) as c FROM login_attempts
WHERE ip = ? AND success = 0 AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)",
[$ip]
)['c'];
if ($recentFailures >= $threshold) {
SecurityHelper::blockIp($ip);
}
}
Once an IP lands in blocked_ips, it stays blocked until it's manually cleared or the block expires, depending on how the installation is configured — there's no per-second sliding window to reason about, just a straightforward attempt count over a rolling period.
What jekcms Doesn't Do (and Why That's Fine)
There's no separate, general-purpose rate-limiting class covering arbitrary actions with configurable per-action limits and file-based counters. The login-attempt protection above is specific to authentication. For the REST API, the relevant control is a simple per-key request-per-minute cap (see the API documentation) rather than a shared sliding-window rate limiter reused across every subsystem. If your installation needs broader rate limiting for a custom endpoint you're building, that's something you'd add yourself — jekcms's core focuses its built-in protection where it matters most: the login form.
Practical Impact
The practical effect for a site owner: an attacker running a credential-stuffing list against your login form runs out of attempts from a given IP well before they'd get through any meaningful fraction of a password list, and legitimate users who mistype their password a few times in a row are never affected by thresholds set for that kind of everyday behaviour.