Error when entering the access system, the session is lost and data is recorded failed when entered correctly?

2

When the user enters correctly with the access data to the system, it registers in the database failed attempts in the following tables.

  

failed_attempt This table posts every failed attempt as a registered or unregistered user, all failed attempts are counted.

  

failed_login This table records failed attempts of a user who is registered in the system obtaining his id - > id_user

  

You should not record failed attempts in the tables, because the user entered the correct data and accessed the system, therefore you should not register failed attempts.

Failed attempts must be recorded when sending blank data, when a user is entered that does not exist, when a correct user is entered and a wrong password is entered. All this works correctly, the error is presented when accessing the system correctly registers failed attempts when it should not because you are accessing the system correctly.

The second error occurs in the session , apparently the session is being destroyed or it is not validating correctly when the user enters the data correctly in the login (login.php) this is redirected to the main page (index.php) everything seems to be perfect but it is not.

  

Because when modifying the Urls or clicking on the <a href="login.php">Iniciar Sesión</a> link to access the login.php page, I can access login and should not be able to enter the login because I have already started sesión should redirect me back to the main page but it does not.

index.php

<?php
    session_start();
    /*if(!isset($_SESSION["id_user"])) {
        header("location:login.php");
    }*/

    function logged_in(){
        return (isset($_SESSION['id_user'])) ? true : false;
    }
?>
<!doctype html>
<html lang="en">
<head>
</head>
<body>
    <div class="boton">
    <?php
      if (logged_in() === true){
        echo "Usuario logueado";
      }else{
        echo "usuario no logueao";
       }
    ?>
    </div>
    <div><a href="login.php">iniciar sesion</a></div>
</body>
</html>

login.php

<?php
session_start();
if (isset($_POST)) {
    $message= $username =  $password = $usernameBD = $passwordDB = NULL;
    $captcha = true;
    //indicador usuario logueado
    $logueado = false;
    //Nro intentos permitidos para IP
    $attemptsIP = 8;
    //Nro intentos permitidos para Usuario
    $attemptsU = 5;

    if(isset($_POST) && isset($_POST["vcode"]) && $_POST["vcode"]!=$_SESSION["vcode"]) {
    $captcha = false;
    $message = "Los caracteres escritos no coinciden con la palabra de verificación. Inténtalo de nuevo.";
  }else{
    unset($_SESSION['id_user']);
  }

  $addres = $_SERVER['REMOTE_ADDR'];

  //Conexión -> SQL
  require_once'app/php/config.ini.php';
  //Bloqueamos la ip por un día
  $stmtA = $con->prepare("SELECT attempts FROM failed_attempt WHERE ip=? AND datetime BETWEEN DATE_SUB( NOW() , INTERVAL 1 DAY ) AND NOW()");

  $stmtA->bind_param("s",$addres);
  $stmtA->execute();
  $stmtA->store_result();

  //Variable para saber si existe registro o no para insert o update.
  $check_result = $stmtA->num_rows;
  if ($stmtA->num_rows===1) { 
  //if ($stmtA->num_rows>0) {
    //Obtenemos datos para comparar intentos y para resetear intentos por su ultimo fecha.
    $stmtA->bind_result($failed_login_attempt);
    $stmtA->fetch();
    $stmtA->close();
  } else {
    $stmtA->close();
    $failed_login_attempt=0;
  }

  if(count($_POST)>0 && $captcha == true) {
    $username = $_POST["username"] ?: '';
    $password = $_POST["password"] ?: '';    

    //Buscar usuario ingresado - INICIO
    $stmtB = $con->prepare("SELECT id_user,username,password,logindatetime, CASE WHEN logindatetime BETWEEN DATE_SUB( NOW() , INTERVAL 2 MINUTE ) AND NOW() THEN '1' ELSE '0' END as logueado FROM users where username=? AND active=? LIMIT 1");
    $stmtB->bind_param("si",$username,$active);
    $active=1;
    $stmtB->execute();
    $stmtB->store_result();
    if ($stmtB->num_rows===1) {
        $stmtB->bind_result($id_userBD,$usernameBD,$passwordDB,$logindatetime,$activeBD);
        if ($stmtB->fetch()){
            if (password_verify($password, $passwordDB)) {
                $check_password = true;
            } else {
                $check_password = false;
            }
        } $stmtB->close();
      } else {
        $stmtB->close();
        $check_password = false;
      }

      //Buscar usuario ingresado - FIN

      //registra intentos de login segun IP - INICIO
      //if ($check_username == false) { 

      if($check_result===0){

        //Si es su primer intento fallido, incluimos el primer registro en la BD
        $stmtC = $con->prepare("INSERT INTO failed_attempt (ip,attempts,datetime) VALUES (?, ?, NOW())");
        $stmtC->bind_param("si",$addres,$attempts);

        $attempts = 1;
        //$datetime = date('Y-m-d  H:i:s', time());
        $stmtC->execute();
        $stmtC->close();

      } else {
        //se actualiza mientras el nro de intentos este abierto, para evitar bug con calculo del dia bloqueado

        if($failed_login_attempt<$attemptsIP){
          $accountant = $failed_login_attempt + 1; 

          $stmtD = $con->prepare("UPDATE failed_attempt SET attempts=?, datetime=NOW() WHERE ip = ?");
          $stmtD->bind_param("is",$accountant,$addres); 

          //$datetime = date('Y-m-d  H:i:s', time());
          $stmtD->execute();
          $stmtD->close();
      }
  }
//}
      //registra intentos de login segun IP - FIN

      //VALIDANDO DOBLE LOGUEO

      if ($username==$usernameBD && $check_password == true && $logindatetime!=NULL && $activeBD==1) {
        $logueado = true;
      } else {
        //registra intentos segun usuario - INICIO
        $attempU = 0;

        if($usernameBD!= null && $usernameBD!=''){

            $id_user = $id_userBD;

            //Sentencia
            $stmtE = $con->prepare("SELECT attempts FROM failed_login WHERE id_user =? AND datetime BETWEEN DATE_SUB( NOW() , INTERVAL 15 MINUTE ) AND NOW() ");
            $stmtE->bind_param("i",$id_user);
            $stmtE->execute();
            $stmtE->store_result();
            $queryResult = $stmtE->num_rows;

            if ($queryResult===0) {
                $stmtF = $con->prepare("INSERT INTO failed_login (id_user, attempts, ip, datetime) VALUES (?, ?, ?, NOW())"); 
                $stmtF->bind_param("iis",$id_user,$attempts,$addres); 
                $attempts=1; 
                $stmtF->execute(); 
                $stmtF->close();
            } else {
                $stmtE->bind_result($attempU_BD);
                $stmtE->fetch();

                $attempU = $attempU_BD+1;

                if ($attempU_BD<$attemptsU) {
                    $stmtG = $con->prepare("UPDATE failed_login SET attempts=?, ip = ?, datetime=NOW() where id_user =?");
                    $stmtG->bind_param("isi",$attempU,$addres,$id_user);
                    $stmtG->execute();
                    $stmtG->close(); 
                }

            } $stmtE->close();
        }
        //registra intentos segun usuario - FIN     
      }  

      //validando Usuario y Contraseña - INICIO

      if (empty($username) || empty($password)) {
        $message = "Es necesario introducir un nombre de usuario y contraseña";
      } elseif($failed_login_attempt>=$attemptsIP){
        $message = "'IP' bloqueada por 1 dia";
      } elseif($logueado){
        $message = "'Usuario' ya se encuentra logueado.";
      } elseif($attempU>=$attemptsU){
        $message = "'Usuario' bloqueado por 15 minutos";
      } elseif ($username != $usernameBD ) {
        $message = "El 'Usuario' que has introducido no coincide. ";
      } elseif ($check_password == false) {        
        $message = "Tu 'Contraseña' introducido no coincide. ";
      } else {
        $_SESSION["id_user"] = $id_userBD;
        //$con->query("DELETE FROM failed_attempt WHERE ip = '$addres'");
        //$con->query("DELETE FROM failed_login WHERE id_user ='$id_user'");
      }
      //validando Usuario y Contraseña - FIN
      if(isset($_SESSION["id_user"])) {
        //echo '<script>window.location="index.php"</script>';
        header('location:index.php');exit;
      }

    }
  }
?>
  

Note: By correctly entering the system and accessing the login.php that should not be able to because I have already logged in when returning to the main page it shows me the message not logged you are losing or destroying the session should not because there is not yet the code to destroy the session

    
asked by J. Mick 26.09.2017 в 06:41
source

2 answers

2

login.php

  

You should not record failed attempts in the tables, because the user entered the correct data and accessed the system, therefore you should not register failed attempts.

Guilty: if($usernameBD!= null && $usernameBD!=''){

In this line you are comparing if $usernameBD is different from NUll , that is, if it is started, continue and insert the failure.

Now think when you log in and put your data right, your statement creates $usernameBD , since that variable is obtained from your sentence if the user exists in the comparison of your SELECT , links to $usernameBD from the Database , then you will always insert the failure if you put the user correctly, because $usernameBD yes also exists in your case.

To correct this error, replace the line above with this:

if($check_username==true && $check_password == false){

That is to say, here we are saying if the username is correct but the password is false, insert the error, so you will avoid when you log in correctly, do not insert the fault.

  

Note: $check_username It does not exist yet in your code, you must enter it in the following way:

if ($stmtB->num_rows===1) {
        $stmtB->bind_result($id_userBD,$usernameBD,$passwordDB,$logindatetime,$activeBD);
        if ($stmtB->fetch()){

          //Usuario existe, creo variable de existencia //////////////////////////
          $check_username = true;
          ///////////////////////////////////////////////////////////////////////

            if (password_verify($password, $passwordDB)) {
                $check_password = true;
            } else {
                $check_password = false;
            }
        } $stmtB->close();
      } else {
        $stmtB->close();
        //Caso falso, Usuario no existe//////////////////////
        $check_username = false;
        ////////////////////////////////////////////////////
        $check_password = false;
      }
  

At your second fault.

To avoid double login, I do not see in your code that you create the statement where you update the login date in login.php .

Try to see add the following to your code to see if it works like this and send you a message of already logged in:

  //validando Usuario y Contraseña - FIN
  if(isset($_SESSION["id_user"])) {

    //Vamos a probar añadir un datetime al usuario cuando inicia sesión, para asi saber si esta iniciado o no, sino sera dificil de saber si alguien esta iniciado sesión :).

    //Actualizamos el logindatetime cuando usuario inicia sesión.
    $stmtU = $con->prepare("UPDATE users SET logindatetime = NOW() WHERE id_user=?");
    $stmtU->bind_param("i",$id_userBD);
    $stmtU->execute();
    $stmtU->close();

    echo '<script>window.location="index.php"</script>';        
  }

Log in from two different browsers to do the test, and in the second I show the message of the image:

I did the test in localhost , with your index.php as is, without modifying it.

Response to your comment: (failed_attempt)

Your constructor if($check_result===0){(toda su información)} should go inside this new one that I will leave in the example below if ($check_username == false OR $check_password==false) { , that is, if the user is false or the password is false, enter an attempt in failed_attemp

//Buscar usuario ingresado - FIN

//registra intentos de login segun IP - INICIO
if ($check_username == false OR $check_password==false) { 

    if($check_result===0){

          //Si es su primer intento fallido, incluimos el primer registro en la BD
          $stmtC = $con->prepare("INSERT INTO failed_attempt (ip,attempts,datetime) VALUES (?, ?, NOW())");
          $stmtC->bind_param("si",$addres,$attempts);

          $attempts = 1;
          //$datetime = date('Y-m-d  H:i:s', time());
          $stmtC->execute();
          $stmtC->close();

   } else {
          //se actualiza mientras el nro de intentos este abierto, para evitar bug con calculo del dia bloqueado

          if($failed_login_attempt<$attemptsIP){
            $accountant = $failed_login_attempt + 1; 

            $stmtD = $con->prepare("UPDATE failed_attempt SET attempts=?, datetime=NOW() WHERE ip = ?");
            $stmtD->bind_param("is",$accountant,$addres); 

            //$datetime = date('Y-m-d  H:i:s', time());
            $stmtD->execute();
            $stmtD->close();
          }
   }
}
//registra intentos de login segun IP - FIN
    
answered by 26.09.2017 / 22:45
source
0

Something like this:

The html

<?php
    session_start();
    /*if(!isset($_SESSION["id_user"])) {
        header("location:login.php");
    }*/

    function logged_in(){
        if(!isset($_SESSION['id_user'])){
  header("location: login.php");
exit;
}
    }
?>
<!doctype html>
<html lang="en">
<head>
</head>
<body>
    <div class="boton">
    <?php
      if (logged_in() === true){
        echo "Usuario logueado";
      }else{
        echo "usuario no logueao";
       }
    ?>
    </div>
    <div><a href="login.php">iniciar sesion</a></div>
</body>
</html>

The login:     

if(isset($_SESSION["id_user"])) {
        //echo '<script>window.location="index.php"</script>';
  header('location:index.php');exit;
}else{
  if (isset($_POST)) {
    $message= $username =  $password = $usernameBD = $passwordDB = NULL;
    $captcha = true;
    //indicador usuario logueado
    $logueado = false;
    //Nro intentos permitidos para IP
    $attemptsIP = 8;
    //Nro intentos permitidos para Usuario
    $attemptsU = 5;

    if(isset($_POST) && isset($_POST["vcode"]) && $_POST["vcode"]!=$_SESSION["vcode"]) {
      $captcha = false;
      $message = "Los caracteres escritos no coinciden con la palabra de verificación. Inténtalo de nuevo.";
    }else{
      unset($_SESSION['id_user']);
    }

    $addres = $_SERVER['REMOTE_ADDR'];

  //Conexión -> SQL
    require_once'app/php/config.ini.php';
  //Bloqueamos la ip por un día
    $stmtA = $con->prepare("SELECT attempts FROM failed_attempt WHERE ip=? AND datetime BETWEEN DATE_SUB( NOW() , INTERVAL 1 DAY ) AND NOW()");

    $stmtA->bind_param("s",$addres);
    $stmtA->execute();
    $stmtA->store_result();

  //Variable para saber si existe registro o no para insert o update.
    $check_result = $stmtA->num_rows;
    if ($stmtA->num_rows===1) { 
  //if ($stmtA->num_rows>0) {
    //Obtenemos datos para comparar intentos y para resetear intentos por su ultimo fecha.
      $stmtA->bind_result($failed_login_attempt);
      $stmtA->fetch();
      $stmtA->close();
    } else {
      $stmtA->close();
      $failed_login_attempt=0;
    }

    if(count($_POST)>0 && $captcha == true) {
      $username = $_POST["username"] ?: '';
      $password = $_POST["password"] ?: '';    

    //Buscar usuario ingresado - INICIO
      $stmtB = $con->prepare("SELECT id_user,username,password,logindatetime, CASE WHEN logindatetime BETWEEN DATE_SUB( NOW() , INTERVAL 2 MINUTE ) AND NOW() THEN '1' ELSE '0' END as logueado FROM users where username=? AND active=? LIMIT 1");
      $stmtB->bind_param("si",$username,$active);
      $active=1;
      $stmtB->execute();
      $stmtB->store_result();
      if ($stmtB->num_rows===1) {
        $stmtB->bind_result($id_userBD,$usernameBD,$passwordDB,$logindatetime,$activeBD);
        if ($stmtB->fetch()){
          if (password_verify($password, $passwordDB)) {
            $check_password = true;
          } else {
            $check_password = false;
          }
        } $stmtB->close();
      } else {
        $stmtB->close();
        $check_password = false;
      }

      //Buscar usuario ingresado - FIN

      //registra intentos de login segun IP - INICIO
      //if ($check_username == false) { 

      if($check_result===0){

        //Si es su primer intento fallido, incluimos el primer registro en la BD
        $stmtC = $con->prepare("INSERT INTO failed_attempt (ip,attempts,datetime) VALUES (?, ?, NOW())");
        $stmtC->bind_param("si",$addres,$attempts);

        $attempts = 1;
        //$datetime = date('Y-m-d  H:i:s', time());
        $stmtC->execute();
        $stmtC->close();

      } else {
        //se actualiza mientras el nro de intentos este abierto, para evitar bug con calculo del dia bloqueado

        if($failed_login_attempt<$attemptsIP){
          $accountant = $failed_login_attempt + 1; 

          $stmtD = $con->prepare("UPDATE failed_attempt SET attempts=?, datetime=NOW() WHERE ip = ?");
          $stmtD->bind_param("is",$accountant,$addres); 

          //$datetime = date('Y-m-d  H:i:s', time());
          $stmtD->execute();
          $stmtD->close();
        }
      }
//}
      //registra intentos de login segun IP - FIN

      //VALIDANDO DOBLE LOGUEO

      if ($username==$usernameBD && $check_password == true && $logindatetime!=NULL && $activeBD==1) {
        $logueado = true;
      } else {
        //registra intentos segun usuario - INICIO
        $attempU = 0;

        if($usernameBD!= null && $usernameBD!=''){

          $id_user = $id_userBD;

            //Sentencia
          $stmtE = $con->prepare("SELECT attempts FROM failed_login WHERE id_user =? AND datetime BETWEEN DATE_SUB( NOW() , INTERVAL 15 MINUTE ) AND NOW() ");
          $stmtE->bind_param("i",$id_user);
          $stmtE->execute();
          $stmtE->store_result();
          $queryResult = $stmtE->num_rows;

          if ($queryResult===0) {
            $stmtF = $con->prepare("INSERT INTO failed_login (id_user, attempts, ip, datetime) VALUES (?, ?, ?, NOW())"); 
            $stmtF->bind_param("iis",$id_user,$attempts,$addres); 
            $attempts=1; 
            $stmtF->execute(); 
            $stmtF->close();
          } else {
            $stmtE->bind_result($attempU_BD);
            $stmtE->fetch();

            $attempU = $attempU_BD+1;

            if ($attempU_BD<$attemptsU) {
              $stmtG = $con->prepare("UPDATE failed_login SET attempts=?, ip = ?, datetime=NOW() where id_user =?");
              $stmtG->bind_param("isi",$attempU,$addres,$id_user);
              $stmtG->execute();
              $stmtG->close(); 
            }

          } $stmtE->close();
        }
        //registra intentos segun usuario - FIN     
      }  

      //validando Usuario y Contraseña - INICIO

      if (empty($username) || empty($password)) {
        $message = "Es necesario introducir un nombre de usuario y contraseña";
      } elseif($failed_login_attempt>=$attemptsIP){
        $message = "'IP' bloqueada por 1 dia";
      } elseif($logueado){
        $message = "'Usuario' ya se encuentra logueado.";
      } elseif($attempU>=$attemptsU){
        $message = "'Usuario' bloqueado por 15 minutos";
      } elseif ($username != $usernameBD ) {
        $message = "El 'Usuario' que has introducido no coincide. ";
      } elseif ($check_password == false) {        
        $message = "Tu 'Contraseña' introducido no coincide. ";
      } else {
        $_SESSION["id_user"] = $id_userBD;
        //$con->query("DELETE FROM failed_attempt WHERE ip = '$addres'");
        //$con->query("DELETE FROM failed_login WHERE id_user ='$id_user'");
      }
      //validando Usuario y Contraseña - FIN

    }
  }
}
?>
    
answered by 26.09.2017 в 13:59