How to travel with PDO

1

I'm trying to login and I'm using PDO. This is my code

Form

<form method="POST" action="ajax.php?mode=login" class="form-signin">

          <h1 class="h3 mb-3 font-weight-normal">Iniciar Sesión</h1>
          <label for="inputUser" class="sr-only">Usuario</label>
          <input type="text" name="user" id="inputUser" placeholder="Usuario" required autofocus>

          <input type="password" name="pass" id="inputPass" placeholder="Contraseña"  required>
          <div class="checkbox mb-3">
            <label>
              <input type="checkbox" value="remember-me"> Recordar me
            </label>
          </div>
          <button class="btn-primary" type="submit">Iniciar Sesión</button>
          <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
        </form>

PHP Code

if(!empty($_POST['user']) AND !empty($_POST['pass'])) {

        $db=Conexion::conectar();
        $usuario = $_POST['user'];
        $pass = $_POST['pass'];

        $sql=$db->query("SELECT empleado.id_empleado, empleado.cedula, datos_empleado.nombre, datos_empleado.apellido,  datos_empleado.sueldo, empleado.usuario, empleado.correo, empleado.telefono, direc_ciudad.ciudad, roles.roles FROM empleado INNER JOIN datos_empleado ON empleado.id_empleado=datos_empleado.id_empleado INNER JOIN direc_ciudad ON empleado.id_ciudad=direc_ciudad.id_ciudad INNER JOIN roles ON datos_empleado.id_roles=roles.id_roles WHERE usuario='$usuario' AND pass='$pass' LIMIT 1;");
         $sql->execute();
        $fila=$sql->fetch(PDO::FETCH_ASSOC);
        var_dump($fila);

    }else {
         echo '<script>
        alert("Error ! El Usuario y/o Contraseñas son Incorrectos");
        window.history.go(-1); 
        </script>
        ';
    }

When I go through the query, it does not find data, I throw a var_dump to the variable $fila and it returns a bool (false) but I know that the query is well done. p>

Why will it be?

    
asked by Jdavid Barajas 07.07.2018 в 16:16
source

1 answer

2

A query can fail for many reasons, among them, that the connection to the DB is null, that there is a syntax error in it ... there may also be empty queries because the criteria are not met. It can fail due to a coding problem, when there is content with accents or ñ and coding is not being handled well, etc, etc, etc.

Here you are making another mistake, which is wrong using the prepared queries, which exist precisely so as not to pass data from variables coming from abroad directly in the query, due to the serious risk of SQL injection .

You are also mixing two concepts: unprepared queries, in which query is used, and queries prepared in which use prepare ... execute . By using on the one hand query and another execute , there is a mixture of concepts that will necessarily lead to error (Thanks @LuiscYm).

As a solution, you can change the variables by markers in the SQL statement, and pass those variables in the form of an array in execute . That way the code is shielded against the injection.

You will see that where you put this in the query: WHERE usuario='$usuario' AND pass='$pass' I have put this: WHERE usuario=? AND pass=? , that way, the variables do not travel directly to run in the query, because a user malicious can fix them to introduce malicious code in them. You will also see that I have created an array with the variables called $arrParams and I pass that array in the execute . That way, if there is misleading data in the PDO variables, it will detect them and prevent the cheat query from being executed to your doom :). It is thus briefly explained how the prepared consultations work.

Since the execution may still fail, I have put a control structure for it, printing the error message in case the query fails.

This is only a proposal, since depending on the context, it is not always convenient to show everything to the user. You can therefore control when there is an error and show a personalized message, taking only part of what errorInfo throws.

Try this code, in which I have applied everything said above. Also, to obtain the variables I used a style that seems more clean , taking advantage of the ternary operators (that you can leave as you had if you prefer).

Test and comment on the result:

/*
    *Una técnica quizá más limpia consiste en usar operadores ternario
    *que nos permiten evaluar el POST y asignar su valor a variables
    *o NULL en caso de que estén vacías
    *Luego ya tenemos las variables y sólo controlamos su estado
*/
$usuario = (!empty($_POST['user'])) ? $_POST['user'] : NULL;
$pass    = (!empty($_POST['pass'])) ? $_POST['pass'] : NULL;

if($usuario && $pass) {
    $db=Conexion::conectar();
    if($db){
        $strSQL="SELECT 
                        empleado.id_empleado, 
                        empleado.cedula, 
                        datos_empleado.nombre, 
                        datos_empleado.apellido,  
                        datos_empleado.sueldo, 
                        empleado.usuario, 
                        empleado.correo, 
                        empleado.telefono, 
                        direc_ciudad.ciudad, 
                        roles.roles
                 FROM empleado 
                    INNER JOIN datos_empleado ON empleado.id_empleado=datos_empleado.id_empleado 
                    INNER JOIN direc_ciudad ON empleado.id_ciudad=direc_ciudad.id_ciudad 
                    INNER JOIN roles ON datos_empleado.id_roles=roles.id_roles 
                 WHERE usuario=? AND pass=? LIMIT 1;"
        $sql=$db->prepare($strSQL);
        $arrParams=array($usuario,$pass);
        if ($sql->execute($arrParams)){
            $fila=$sql->fetch(PDO::FETCH_ASSOC);
            var_dump($fila);
        }else{
            print_r($db->errorInfo());
        }

    }else{
        echo "No hay conexión a la BD";
    }
}else{
    echo '<script>
            alert("Error ! El Usuario y/o Contraseñas son Incorrectos");
            window.history.go(-1); 
          </script>
         ';
}
    
answered by 07.07.2018 в 16:33