How to Secure Login APIs: Defending Against Brute‑Force, MITM, and More
This article explains practical security measures for login interfaces, covering brute‑force attacks, captcha integration, IP throttling, mobile verification, man‑in‑the‑middle protection with HTTPS, and additional best‑practice recommendations to harden web back‑end authentication.
When learning programming the first line is usually "hello world", but in web back‑end development many beginners start with a login feature. Although they may list "responsible for login/registration module development" on their résumé, they often ignore security considerations.
Security Risks
Brute‑Force Attack
If a website is exposed to the public network, attackers may try to brute‑force passwords by iterating over possible passwords after obtaining usernames.
# password dictionary
password_dict = []
# login endpoint
login_url = ''
def attack(username):
for password in password_dict:
data = {'username': username, 'password': password}
content = requests.post(login_url, data).content.decode('utf-8')
if 'login success' in content:
print('got it! password is : %s' % password)How can we prevent this?
Captcha
After a certain number of failed password attempts, require a captcha verification.
fail_count = get_from_redis(fail_username)
if fail_count >= 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
success = do_login(username, password)
if not success:
set_redis(fail_username, fail_count + 1)Login Restriction
Lock the account after many failed attempts.
fail_count = get_from_redis(fail_username)
locked = get_from_redis(lock_username)
if locked:
return error('拒绝登录')
if fail_count >= 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
success = do_login(username, password)
if not success:
set_redis(fail_username, fail_count + 1)
if fail_count + 1 >= 10:
# lock for 300 seconds
set_redis(lock_username, true, 300s)While this stops password‑cracking, an attacker could lock out all users by repeatedly trying random usernames.
IP Restriction
Throttle login attempts per IP address.
ip = request['IP']
fail_count = get_from_redis(fail_ip)
if fail_count > 10:
return error('拒绝登录')
# other logic
success = do_login(username, password)
if not success:
set_redis(fail_ip, true, 300s)Problems with pure IP limiting:
Shared outbound IPs (e.g., in schools or companies) may cause legitimate users to be blocked.
Attackers can switch VPNs to bypass IP bans.
Mobile Verification
Combine captcha with SMS‑based mobile verification for stronger authentication.
fail_count = get_from_redis(fail_username)
if fail_count > 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
if fail_count > 10:
if dynamic_code is None:
return error('请输入手机验证码')
if not validate_dynamic_code(username, dynamic_code):
delete_dynamic_code(username)
return error('手机验证码错误')
success = do_login(username, password, dynamic_code)
if not success:
set_redis(fail_username, fail_count + 1)These combined measures raise the attack cost, though no system is absolutely secure.
Man‑in‑the‑Middle (MITM) Attack?
What Is MITM?
A MITM attack occurs when an attacker intercepts or modifies communication between two parties (A and B), potentially stealing credentials such as usernames and passwords during login.
HTTPS
Switching to HTTPS is the simplest and most effective way to prevent MITM attacks.
Why HTTPS Helps
Content encryption
Data integrity
Identity authentication
Detailed HTTPS internals are omitted; you can search online for more information.
Encrypted Transmission
Beyond HTTPS, you can manually encrypt sensitive data:
Encrypt usernames on the client with asymmetric encryption, decrypt on the server.
Hash passwords with MD5 (or stronger algorithms) before transmission to avoid plain‑text exposure.
Other Recommendations
Operation logs: record each login and sensitive operation (IP, device, etc.).
Abnormal login alerts: send SMS or other notifications when risky actions occur.
Reject weak passwords during registration or password changes.
Prevent username enumeration by limiting feedback on username existence checks.
…
Postscript
With increasing regulations on user data, developers must take more responsibility for protecting privacy. Future articles will discuss additional data‑security practices.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
