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 If 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.

Sources and verification

Verify release and technical details with these primary sources.

Written by

Celil Uyanıkoğlu

Computer engineer with 25+ years in IT. He builds jekcms and runs his own network of content sites on it — every guide published here is tried on those live installs first.

See all posts →

Order Today

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

View Pricing
  • Setup and live in 30 minutes
  • 13 professional themes
  • AVIF/WebP image optimization
  • Automatic SEO — Sitemap, Schema.org
  • ZeroTrack cookieless analytics

Be the first to know

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