[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 12644
  • Last Modified:

php block login for 15 minutes after 3 failed attempts

Hi
I have a logjn script which records the ip address, the number of attempts and the time of attempt to a mssql database when a user tries to log in, it gives the user 3 attempts to login and them blocks them. This is all working fine.

My problem is i only want the ip address to be blocked for 'x' minutes so that the user can try logging in again without me having to manually change the value of attempts in the database

Any ideas on what code i should add to do this?

here is my code:

<?php
session_start();
include('connection to the database');

//get ip address
$ip=$_SERVER['REMOTE_ADDR'];

//get current time  
$today=date("d/m/y H:i:s");

//get username and password from form
$login =  $_POST['login'];
$password = $_POST['password'];

//check if ip address has been used before
$checkip=mssql_query("SELECT * FROM login_attempts WHERE IpAddress='$ip'");
$row=mssql_fetch_array($checkip);
$ipaddress=$row['IpAddress'];  
$previousattempts=$row['attempts'];


//variables to be used to set number of attempts  
$currentattempt = $previousattempts + 1;
$successfullogin = 0;
$firstattempt = 1;

//if ip address is not used before
if($ipaddress !=$ip)
{
    //add new ip address to database
    mssql_query("INSERT INTO login_attempts (IpAddress, attempts, date_last_use) VALUES('$ip','$firstattempt', '$today')");
    mssql_close();

    // check login details
    if (isset($_POST['login']) && isset($_POST['password']))
    {
        //code for checking login details is here
    }

            //on successful login set attempts to 0 and direct to members page
            @mssql_query("UPDATE login_attempts SET attempts = '$successfullogin', date_last_use = '$today' WHERE IpAddress = '$ip' ");
            mssql_close();
               
            @header("location: member-index.php");
        }
    }
    else //if login failed
    {
        //redirect to login failed page
        @header("location: login-failed.php");
    }
}

else  //if ip address is found in database
{
    //check if number of attempts is < 3
    if ($row['attempts'] < 3)
    {
        // check login details
        if (isset($_POST['login']) && isset($_POST['password']))
        {
      //code for checking login details is here
        }


                //on successful login set attempts to 0 and direct to members page
                @mssql_query("UPDATE login_attempts SET attempts = '$successfullogin', date_last_use = '$today' WHERE IpAddress = '$ip' ");
                mssql_close();
               
                @header("location: member-index.php");
            }
            else // failed login - add 1 to number of attempts
            {
                @mssql_query("UPDATE login_attempts SET attempts = '$currentattempt', date_last_use = '$today' WHERE IpAddress = '$ip' ");
                mssql_close();
       
            //redirect to login failed page
            @header("location: login-failed.php");  
            }
        }
    }
    else  failed login - add 1 to number of attempts
    {
        @mssql_query("UPDATE login_attempts SET attempts = '$currentattempt', date_last_use = '$today' WHERE IpAddress = '$ip' ");
        mssql_close();
        //redirect to login failed page
        @header("location: login-failed.php");  
    }
}
?>
0
CoreSupport
Asked:
CoreSupport
1 Solution
 
Sebastian TalmonSystem Engineer Datacenter SolutionsCommented:

do you need to block the IP or the user for 15 minutes?

A solution for blocking the username would be simpler as you could simply use another column in the user-database.
A solution based on the IP would require another table for the IP's.

There are pros an cons for both solutions - a block based on IP would somewhat block trial/error-guesses of usernames, with only one ore two tries of passwords per username - the other solution is better if you have only few users, and hackers might try to use a botnet ore some distributed hosts with different IPs to break into one specific account

Wich one would you prefer?
0
 
CoreSupportAuthor Commented:
i want to work with blocking the ip address as i already have a table in the database which records ip address, the number of attempts made and the time of last attempt, and the code i posted is all working,
 
i just need to add some code which will reset attempts to zero after 15 minutes of inactivity from that ip address, and so this would allow 3 more attempts from that ip.

is there a function that can check the difference between two date/times? i could use something like that to calculate the difference between time of last attempt in database and the current time, and if differnce > 15 minutes, reset attempts to zero
0
 
Sebastian TalmonSystem Engineer Datacenter SolutionsCommented:

first of all, I would recommend that you do the date-calculations and also the calculation of the failed logins completely in mysql, and not in php - it decreases the need of php-code and traffic to/from the database.

Do you know the posibilities of the data-type "TIMESTAMP" in mysql?
If you set a column as TIMESTAMP and the default-value to NULL, the current date/time is added automaticly with new entries - no need to construct some $today variable in php...
For normal date/time-columns, you could use the mysql-function "NOW()" instead of $today in the query - mysql would replace this with the current date/time for you.

you will get the php-code that I would recommend for this with my next comment.
0
Will You Be GDPR Compliant by 5/28/2018?

GDPR? That's a regulation for the European Union. But, if you collect data from customers or employees within the EU, then you need to know about GDPR and make sure your organization is compliant by May 2018. Check out our preparation checklist to make sure you're on track today!

 
CoreSupportAuthor Commented:
im using mssql, not mysql, does timestamp work the same way with this?

the ip address is only saved in the database once, and the number of attempts and and time is updated each time someone tries logging in from that ip. so altough current time can be added as default when an ip address is first used, the $today variable is being used in the update queries to update the time of last login attempt, so it is still needed.

how would i do the calculations completely in mssql?
0
 
Sebastian TalmonSystem Engineer Datacenter SolutionsCommented:

ups - my mistake! don't know why I read mysql...

As with many things, Microsoft uses the timestamp-type for other things than the SQL-Standard prefers ;-)  so you have to stick with date/time-type.

Instead of setting the false login tries to "0" I would just delete any IP-Adress that is not used for over 15 minutes - it also keeps your database small.
Or do you need to record all ever used IP-Adresses?
0
 
Sebastian TalmonSystem Engineer Datacenter SolutionsCommented:

with MSSQL, you could specify GETDATE() as DEFAULT for your date/time-column, so if not specified otherwise, the current date/time is used   (you could see this as equivalent to the timestamp-thing in mysql)


the nice GETDATE() -funtion in MSSQL also leads us to the solution:

just before your
$checkip=mssql_query("SELECT * FROM login_attempts WHERE IpAddress='$ip'");

insert another query:

mssql_query("DELETE FROM login_attempts WHERE DATEDIFF(minute, date_last_use, GETDATE())>15");

(sorry, not tested here as i don't have my MSSQL-server running at the moment)

this should be the simplest solution to your question, without touching to much code.
0
 
CoreSupportAuthor Commented:
thanks tacotec, that query probably would work fine, but i found this function and used it instead:

function getDifference($startDate,$today,$format = 1)
{
    list($date,$time) = explode(' ',$startDate);
    $startdate = explode("-",$date);
    $starttime = explode(":",$time);

    list($date,$time) = explode(' ',$today);
    $enddate = explode("-",$date);
    $endtime = explode(":",$time);

    $secondsDifference = mktime($endtime[0],$endtime[1],$endtime[2],
        $enddate[1],$enddate[2],$enddate[0]) - mktime($starttime[0],
            $starttime[1],$starttime[2],$startdate[1],$startdate[2],$startdate[0]);
     
    switch($format){
        // Difference in Minutes
        case 1:  
            return floor($secondsDifference/60);
        // Difference in Hours    
        case 2:
            return floor($secondsDifference/60/60);
        // Difference in Days    
        case 3:
            return floor($secondsDifference/60/60/24);
        // Difference in Weeks    
        case 4:
            return floor($secondsDifference/60/60/24/7);
        // Difference in Months    
        case 5:
            return floor($secondsDifference/60/60/24/7/4);
        // Difference in Years    
        default:
            return floor($secondsDifference/365/60/60/24);
    }                
}

the start date being the time stored in the database

and then before i checked if attempts < 3 i added this code

$differnce = getDifference($startDate,$today,$format = 1);
   
    if ($differnce>15)
    {
       @mssql_query("UPDATE login_attempts SET attempts = '$successfullogin' WHERE IpAddress = '$ip' ");
       mssql_close();
       $currentattempt = 1;  
    }

which sets attempts to zero if time difference > 15 minutes, giving the user 3 more attempts without having to delete ip address from database

thanks for your ideas anyway
0
 
meproCommented:
You could also do this via the SQL query without having to use a custom function. But since you have selected the answer, I guess its working well for you.

Good luck!
0
 
shweta guptaCommented:
is there any solution  php block login for 15 minutes after 3 failed attempts
0

Featured Post

SMB Security Just Got a Layer Stronger

WatchGuard acquires Percipient Networks to extend protection to the DNS layer, further increasing the value of Total Security Suite.  Learn more about what this means for you and how you can improve your security with WatchGuard today!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now