What are the best practices for balancing security measures, user experience, and performance when implementing anti-brute-force measures in PHP login forms?

One way to balance security, user experience, and performance when implementing anti-brute-force measures in PHP login forms is to use techniques such as rate limiting, CAPTCHA challenges, and account lockouts. These measures can help prevent malicious actors from repeatedly attempting to guess passwords while still allowing legitimate users to access their accounts without significant inconvenience.

// Example implementation of rate limiting in PHP login form

session_start();

$attempts = isset($_SESSION['login_attempts']) ? $_SESSION['login_attempts'] : 0;
$max_attempts = 5;
$timeout = 60; // 1 minute timeout

if ($attempts >= $max_attempts) {
    $remaining_time = $_SESSION['login_time'] + $timeout - time();
    if ($remaining_time > 0) {
        echo "Too many login attempts. Please try again in $remaining_time seconds.";
        exit;
    } else {
        unset($_SESSION['login_attempts']);
        unset($_SESSION['login_time']);
    }
}

// Check login credentials
if ($username == $valid_username && $password == $valid_password) {
    // Successful login
    // Reset login attempts
    unset($_SESSION['login_attempts']);
    unset($_SESSION['login_time']);
} else {
    // Failed login attempt
    $_SESSION['login_attempts'] = $attempts + 1;
    $_SESSION['login_time'] = time();
    echo "Invalid username or password.";
}