Hallo,
Ik ben bezig een loginscript te updaten van mysqli naar PDO. Nu ben ik met behulp van het loginscript van Jeroen VD van 3 jaar geleden een heel eind gekomen, maar ik krijg de inlog-attempt-controle niet aan de praat.
Het script:

<?php
ini_set('display_errors',1); // 1 == on , 0 == off
error_reporting(E_ALL | E_STRICT);
session_start();  
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	$errors = array();
	if (trim($_POST['username']) == '' 
            or (!preg_match('~^[0-9xyzXYZ][0-9]{7}[A-Za-z]$~',($_POST['username']))))
		$errors['username'] = 'Rellena número del NIE o NIF';
	if (trim($_POST['password']) == '' 
            or (!preg_match('~^[0-9]{4}$~', $_POST['password'])))
		$errors['password'] = 'Rellena número socio.';
	if (!empty($_POST['name']))
		 $errors['name'] = 'No valido';
 	if (count($errors) == 0) {
 	//Start procedure
 	try {
	     //Set maximum attempts to login om 3 within 5 minutes
 	     $maxAttempts = 3; 
	     $attemptsTime = 5;
	     //Connect to the dBase
	     require_once ('sql_link_sherpa.php');
 	     //Make the query
	     $sql_select = "SELECT id, nombre, pass FROM socios WHERE dni = :dni";
 	     $userStmt = $db->prepare($sql_select);
 	     $userStmt->execute(array(
			 ':dni' => $_POST['username']
 			));
	     $results = $userStmt->fetchAll();
			
	     //Get logintries for the ultimate 5 minutes
	     $checkTries = "SELECT username FROM loginfail
			WHERE DateAndTime >= NOW() - INTERVAL :attemptsTime MINUTE
			AND username = :username
			GROUP BY username, IP
			HAVING (COUNT(username) = :maxAttempts)";
	     $triesStmt = $db->prepare($checkTries);
	     $triesStmt->execute(array(
		           ':username' => $_POST['username'],
			   ':attemptsTime' => $attemptsTime,
			   ':maxAttempts' => $maxAttempts
			 ));
	     $tries = $triesStmt->fetchAll();
			
	     foreach ($results as $result) {
	     //Check password and set session values			
	          if (count($results) == 1 AND count($tries) <=3) {
			if (count($tries) > 3) {
		        	header ('Refresh: 3; url=index.php');
			        echo 'Too many tries';
			        exit();
		        }
			$hash = $result['pass'];
			if (!password_verify(($_POST['password']), $hash)) {
				$insertTry = "INSERT 
                                           INTO loginfail (username, IP, DateAndTime)
					VALUES ( :username, :IP, NOW())";
				$insertStmt = $db->prepare($insertTry);
				$insertStmt->execute(array(
			                      ':username' => $_POST['username'],
					      ':IP' => $_SERVER['REMOTE_ADDR']
					     ));
				header ('Refresh: 3; url=login.php');
				echo 'Numero incorrecto';
				exit();
			}
			else {
				$_SESSION['logged_in'] = TRUE;
				$_SESSION['id'] = $result['id'];
				$_SESSION['user'] = $result['nombre'];
				header("Location: index_socio.php");  
				exit();
			}
		}		
        
  }
  catch(PDOException $e) {
    $sMsg = '<p>
	Linenumber: '.$e->getLine().'<br />
	File: '.$e->getFile().'<br />
	Errormessage: '.$e->getMessage().'
	</p>';
     trigger_error($sMsg);
  } 
}
}
?>


Het script werkt voorzover als het de passwordcontrole betreft, de meldingen etc. worden correct weergegeven. Is het password fout, dan wordt dit in de database weggeschreven, dus ook hier geen probleem. Alleen krijg ik het niet werkend dat je na 3 pogingen binnen 5 minuten, geen inlogpoging meer kunt doen.
Iemand enig idee?

Excuus dat het script een beetje rommelig eruitziet wat betreft inspringingen. Dat komt door het knippen en plakken.
Ha, ja zo had ik dat nog niet bekeken. Je kunt natuurlijk 2 seconden standaard inbouwen, én dan nog 2 of 3 extra bij een fout ingevoerd password. Dat lijkt me dan wel een effectieve manier.
Nog een andere reden. Brute force hackers proberen vaak ook aan de response van de server te zien of een poging is gelukt of niet. Als je dus hele duidelijke verschillen tussen een goede en foute poging geeft is voor de hacker heel makkelijk te achterhalen welke lukte en welke niet. De ideale manier is om bij mislukte en gelukte inlogpoging precies dezelfde response te geven. Dus even lange wachttijd, zelfde response headers etc.

Reageren