Introduction
Protect your login form from brute force attacks with rate limiting and account lockout.
Key Concepts
Rate Limiting: Limit login attempts.
Account Lockout: Temporarily disable accounts.
Real World Context
Credential stuffing attacks test millions of stolen username/password pairs from data breaches against your login form. Without rate limiting, an attacker can try thousands of combinations per minute. Even a simple 5-attempt lockout with a 15-minute cooldown makes automated attacks impractical.
Deep Dive
Using django-axes
python# pip install django-axes # settings.py INSTALLED_APPS = ['axes', ...] MIDDLEWARE = [ 'axes.middleware.AxesMiddleware', ... ] AUTHENTICATION_BACKENDS = [ 'axes.backends.AxesStandaloneBackend', 'django.contrib.auth.backends.ModelBackend', ] # Configuration AXES_FAILURE_LIMIT = 5 # Lock after 5 failures AXES_COOLOFF_TIME = timedelta(minutes=15) # Lock duration AXES_LOCKOUT_CALLABLE = 'myapp.lockout.lockout_response'
Custom Rate Limiting
pythonfrom django.core.cache import cache def check_rate_limit(request, username): key = f'login_attempts:{username}' attempts = cache.get(key, 0) if attempts >= 5: return False # Locked out cache.set(key, attempts + 1, timeout=900) # 15 min return True
Common Pitfalls
- Locking only by username: An attacker can target different usernames from the same IP. Lock by both IP and username to catch distributed attacks.
- Leaking lockout status: Returning a different error message like "account locked" tells attackers the username is valid. Use the same generic "invalid credentials" message whether the account is locked or the password is wrong.
- No monitoring or alerting: Rate limiting without logging is flying blind. Log every failed attempt with IP, username, and timestamp so your security team can detect coordinated attacks.
Best Practices
- Lock by IP and username: Prevent distributed attacks.
- Use exponential backoff: Increase lockout time.
- Log failed attempts: For security monitoring.
Summary
Use django-axes for production. Configure reasonable limits. Log and monitor failed attempts.