Home » Php » php – What is the best method to prevent a brute force attack?

php – What is the best method to prevent a brute force attack?

Posted by: admin April 23, 2020 Leave a comment


I have my login page and of course I want to prevent brute force attacks and cause less delay for the users when they are logging in.

Currently, you type in your username and password to log in.

I am considering implementing a reCAPTCHA. However, this shows on login after 3 failed attempts.

My question is:

  1. What do you base the attempt on. IP addresses? It can always be hidden… username? What if they’re trying a user that doesn’t exist?

  2. What would be the best method to count the failed login attempts?

How to&Answers:

Sessions are unreliable because they rely on cookies, CAPTCHAs are regularly broken [including ReCAPTCHA]. The only reliable method is deceptively simple: ask a question. Don’t use a math question because computers are surprisingly adept at solving those for some reason. Great old standbys are things like:

  • What is the fourth word in the sixth paragraph on this page?
  • What is the name of the author of this site? [hint]

This is stupid-easy to implement, and very difficult for a machine to solve.

As for bute-forcing, try adding two fields to your user table, ‘first_failed_login’ [INTEGER unix timestamp or DATETIME] and ‘failed_login_count’. [INTEGER]

$bad_login_limit = 3;
$lockout_time = 600;

$first_failed_login, failed_login_count; // retrieve from DB

    ($failed_login_count >= $bad_login_limit)
    (time() - $first_failed_login < $lockout_time)
) {
  echo "You are currently locked out.";
  exit; // or return, or whatever.
} else if( /* login is invalid */ ) {
  if( time() - $first_failed_login > $lockout_time ) {
    // first unsuccessful login since $lockout_time on the last one expired
    $first_failed_login = time(); // commit to DB
    $failed_login_count = 1; // commit to db
  } else {
    $failed_login_count++; // commit to db.
  exit; // or return, or whatever.
} else {
  // user is not currently locked out, and the login is valid.
  // do stuff

This will make your login system recognize only 3 login attempts per user every 10 minutes.


Do not rely on sessions or cookies, those trust the client and you should NEVER trust the client. I made a class that takes care of brute force attack protection in PHP.


it logs all failed logins site-wide in a db table, and if the number of failed logins in the last 10 minutes (or whatever time frame you choose) is over a set limit, it enforces a time delay and/or a captcha requirement before logging in again.


 //build throttle settings array. (# recent failed logins => response).

 $throttle_settings = [

         50 => 2,            //delay in seconds
         150 => 4,           //delay in seconds
         300 => 'captcha'    //captcha 

 $BFBresponse = BruteForceBlocker::getLoginStatus($throttle_settings); 

//$throttle_settings is an optional parameter. if it's not included,the default settings array in BruteForceBlocker.php will be used

 switch ($BFBresponse['status']){

    case 'safe':
         //safe to login
     case 'error':
         //error occured. get message
         $error_message = $BFBresponse['message'];
     case 'delay':
         //time delay required before next login
         $remaining_delay_in_seconds = $BFBresponse['message'];
     case 'captcha':
         //captcha required



Try to check that your are dealing with a real browser.
Maybe some nasty java script challenges with random function names or something could block a lot of simple scripts, unless they remote control a real browser (which is not that uncommon), or evaluate the js/css correctly in the scraper script.

I would recommend to read further on this topic and test your solution against python mechanize or some other well known scraper tools.

But one is for sure, there is no real solution against automatic attacks.