The goal is to keep track of the number of times a login attempt is made from the same ip address within a defined number of seconds. In order to do that the first thing the function does is remove all previously stored attempts from the table that are too old to have happened within that number of seconds. This will keep the table from growing to the point where it might slow the server down and keep it from using too much space. The next step is to add this new attempt to the table, and finally, the script counts the number of attempts from this current ip address and returns the value. From there it's a simple matter for the script to decide whether or not to allow another login attempt based on the defined number of maximum attempts.
<?php
$dsn = "mysql:host=localhost;dbname=test";
$username = "root";
$password = "root";
// Above is my test database information. You'll need to use your own. See Dormilich's tutorial on PDO for more information.
$options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$pdo = new PDO($dsn, $username, $password, $options);
$max_time_in_seconds = 10;
$max_attempts = 3;
if(login_attempt_count($max_time_in_seconds, $pdo) <= $max_attempts) {
echo "Please login<br>";
// Now show the login form
} else {
echo "I'm sorry, you've made too many attempts to log in too quickly.<br>";
// Do not show the login form, since it may be a bot trying to log in.
}
function login_attempt_count($seconds, $pdo) {
try {
// First we delete old attempts from the table
$del_old = "DELETE FROM attempts WHERE `when` < ?";
$oldest = strtotime(date("Y-m-d H:i:s")." - ".$seconds." seconds");
$oldest = date("Y-m-d H:i:s",$oldest);
$del_data = array($oldest);
$remove = $pdo->prepare($del_old);
$remove->execute($del_data);
// Next we insert this attempt into the table
$insert = "INSERT INTO attempts (`ip`, `when`) VALUES ( ?, ? )";
$data = array($_SERVER['REMOTE_ADDR'], date("Y-m-d H:i:s"));
$input = $pdo->prepare($insert);
$input->execute($data);
// Finally we count the number of recent attempts from this ip address
$count = "SELECT count(*) as number FROM attempts where `ip` = ?";
$num = $pdo->prepare($count);
$num->execute(array($_SERVER['REMOTE_ADDR']));
foreach($num as $attempt) {
$attempts = $attempt['number'];
}
return $attempts;
} catch (PDOEXCEPTION $e) {
echo "Error: ".$e;
}
}
The table:
CREATE TABLE `attempts` ( `ip` varchar(20) NOT NULL, `when` datetime NOT NULL, KEY `ip` (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
One more thing: I don't use a form in this demonstration, but you can test the script by reloading the page multiple times.
This post has been edited by CTphpnwb: 26 August 2012 - 09:48 AM






MultiQuote






|