Rate Limiting and Brute Force Protection in JekCMS

How JekCMS tracks failed login attempts and automatically blocks abusive IPs to stop brute force attacks — no Redis, memcached, or external dependency required.

Rate Limiting and Brute Force Protection in JekCMS

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.

Order Today

One-time payment, lifetime access. Setup in 30 minutes.

View Pricing
  • Setup and live in 30 minutes
  • 14+ professional themes
  • n8n automation integration
  • Automatic SEO — Sitemap, Schema.org
  • iyzico payment support

Be the first to know

New features, release notes & CMS guides — a couple of emails a month, no spam.