Here is a complete implementation with number of retries and reCaptcha that I am using on a website I am developing, the only thing that is missing to work 100% is to create the objects, but I have described well how to create them, I am only student then I did the best I could.
<?php ini_set('display_errors',1); ini_set('display_startup_erros',1); error_reporting(E_ALL); ?><!--Força o php a mostrar todo tipo de erro, linha temporária-->
<?php
function __autoload($class_name){
require_once '../_lib/'.$class_name.'.php';//-->lê minhas classes de forma automática
}
?>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="_css/login.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script><scriptsrc='https://www.google.com/recaptcha/api.js'></script><script>$(document).ready(function(){$('#send').prop('disabled',true);//desativaobotãoenviar$('.g-recaptcha').hide();//escondeocaptchavalidate();$('#inputEmail,#inputPassword').change(validate);});functionvalidate(){if($('#inputEmail').val().length>10){//enquantoocampodeemailnaotivermenosque10caracteres,nãoativaoreCaptcha$('.g-recaptcha').show();//exibeoreCaptcha}else{//semudardeideiaereduzirocampopramenosde10caracteres...$('.g-recaptcha').hide();//oreCaptchaseescondenovmanete}}functionenableSend(){$('#send').prop('disabled',false);//quandoocaptchaéconfirmado,ativaobotaoenviar}</script></head><body><?php$helper=newHelpers();//-->objetocomváriosmétodosimportantesif(isset($_POST['attempt'])){//verificasetemtentativarestante$attempt=intval($helper->validation($_POST['attempt']));//validation=métodoqueverificaeescapaminhasring(trim(),stripcslashes()ehtmlspecialchars())}else{$attempt=3;//senãofordefinidonúmerodetentativas,aquiédefinidocomo3}if(isset($_POST['g-recaptcha-response'])andisset($_POST['username'])andisset($_POST['password'])){//garantequetodososcamposforampreenchidos$captcha_data=$_POST['g-recaptcha-response'];if($captcha_data){//VerificaçãodoreCaptcha$resposta=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=DIGITE-SUA-CHAVE-SECRETA-GERADA-PELO-GOOGLE-AQUI=" . $captcha_data . "&remoteip=" . $_SERVER['REMOTE_ADDR']);
if ($resposta) {//validação do reCaptcha
$username = strtolower($helper->validation($_POST['username']));
$password = $helper->validation($_POST['password']);
$user = new User();//--->meu objeto que acessa o banco de dados usando PDO
$userValidated = $user->checkPasswordHash($username);//--->método do meu objeto que procura o usuario no bacno de dados (SELECT * FROM tbl_Users WHERE username = $username)
if ($userValidated){//verifica se o email existe, se existir...
if ($userValidated->status == 1){//verifica se a conta está bloqueada ou não
echo 'Essa conta está bloqueada, criar botão para reenviar o email de recuperação...';
}else{
$hash = $userValidated->password;//retorna o hash do password
if (password_verify($password, $hash)) {//compara a senha e o hash que foi criado usando password_hash() e salvo no banco de dados
echo 'Password é válido, inserir código que inicia as sessões e chama a próxima página';//-->insira seu código
} else {//caso o password estjeja errado, perde uma tentativa
if ($attempt != 1){//se a tentativa restante for igual a 1, a proxima vez será direcionado para a página de recuperação de senha
$attempt--;
echo 'Usuário e senha não combinam, você tem mais '.$attempt.' tentativas';//mostra o número de tentativas restante
}else{//bloqueia a conta e chama a página de recuperação de senha
echo 'inserir código que bloqueia a conta e abre pagina de recuperaçao de senha';//-->insira seu código de bloqueio
}
}
}
}else{//se o email não existir, perde uma tentativa mas não avisa se o erro foi no email ou na senha
if ($attempt != 0){
$attempt--;
echo 'Usuário e senha não combinam, você tem mais '.$attempt.' tentativas';//mostra o número de tentativas restante
}else{//bloqueia a conta e chama a página de recuperação de senha
echo 'inserir código que bloqueia a conta e abre pagina de recuperaçao de senha';//-->insira seu código de bloqueio
}
}
} else {
echo "Validação não concluída, tente novamente.";
exit;
}
} else {
echo "Validação não concluída, tente novamente.";
exit;
}
}
?>
<section>
<form class="login" action="login.php" method="post">
<fieldset>
<legend>Login</legend>
<label for="inputEmail" class="Label">Email: </label>
<input id="inputEmail" class="inputText" type="email" maxlength="30" name="username" required>
<label for="inputPassword" class="Label">Password: </label>
<input id="inputPassword" class="inputPassword" type="password" maxlength="20" name="password" required>
<div class="g-recaptcha" data-sitekey="DIGITE-A-CHAVE-DO-SEU-SITE-CRIADA-PELO-GOOGLE-AQUI" data-callback="enableSend"></div><!--Linha que adiciona o recaptcha-->
<input type="hidden" name="attempt" value=<?php echo $attempt ?> /><!--envia por post o numero de tentativas restante-->
<input type="submit" value="Confirmar" id="send" class="send">
</fieldset>
</form>
</section>
</body>
</html>