How to Secure Login APIs: Prevent Brute‑Force, MITM, and Abuse

This article explains common security risks in login interfaces—such as brute‑force attacks, captcha bypass, account and IP lockouts, man‑in‑the‑middle threats—and provides practical mitigation techniques like password attempt limits, captcha, phone verification, HTTPS, and comprehensive logging.

Java Captain
Java Captain
Java Captain
How to Secure Login APIs: Prevent Brute‑Force, MITM, and Abuse

01 Introduction

When learning web backend development, many developers implement login functionality without considering security, which leaves applications vulnerable.

02 Security Risks

Brute Force

Publicly exposed sites are easy targets for password‑guessing attacks. A simple script can iterate over a password dictionary until a correct credential is found.

# 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)

Captcha

After a configurable number of failed attempts, require a captcha to continue.

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 Limitation

Lock an account after many consecutive failures for a set period.

fail_count = get_from_redis(fail_username)
locked = get_from_redis(lock_username)
if locked:
    return error('拒绝登录')
if fail_count >= 10:
    set_redis(lock_username, true, 300)

IP Limiting

Block an IP address after repeated login failures, while being aware of shared IP and VPN evasion issues.

ip = request['IP']
fail_count = get_from_redis(fail_ip)
if fail_count > 10:
    return error('拒绝登录')
set_redis(fail_ip, true, 300)

Phone Verification

Require SMS or app‑based verification after a higher number of failed attempts to add a second factor.

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)

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)

Man‑in‑the‑Middle (MITM) Attacks

A MITM attacker can intercept or modify traffic between client and server, potentially stealing credentials. Using HTTPS (HTTP over TLS) encrypts the data, ensures integrity, and authenticates the server, effectively mitigating MITM risks.

Content encryption

Data integrity

Identity authentication

Additional Measures

Operation logs that record each login attempt with IP and device information.

Abnormal login alerts (e.g., SMS) for suspicious activities.

Reject weak passwords during registration or password changes.

Prevent username enumeration by limiting lookup responses.

CaptchaHTTPSlogin securityIP rate limitingBrute-force protectionMITM prevention
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.