Cifrar contraseñas usando PHP PDO: Completo
Cifrar contraseñas usando PHP PDO. Por motivos de seguridad es recomendable cifrar las contraseñas y es una nueva forma que ha implementado PHP 7 que te permite conectarte a varios gestores de bases de datos sin tener que alterar demasiado el script de conexión como suele pasar con MySQLi.
En este artículo escribiré de cómo podemos darles seguridad a muestras contraseñas usando PHP y PDO, haremos uso de funciones predeterminadas del lenguaje PHP, conexiones PDO, consultas MySQL, Insert Into.
Preguntas Frecuentes: Cifrar contraseñas usando PHP
¿Cómo funciona el script?
El script primeramente realiza un registro de usuario común, pero a la vez convierte la contraseña ingresada por el usuario y lo cifra usando la función password_hash
y nivel de cost.
Si verificamos la base de datos veremos que la contraseña está cifrada y con su respectivo nivel de cost. Veamos un ejemplo.
$2y$15$dQKzkyyA7pbRmgt9xun/9.LAF1lYEZLX9.wyQyXcmSYbnK6QsKTJW
¿Qué es cost en password_hash?
El parámetro de cost especifica un recuento de iteración de expansión clave como una potencia de dos, que es una entrada al algoritmo de encriptación. Además, un dato a considerar es que a mas cost, más segura será la encriptación.
Por otro lado, mientras más sea el cost, el login de usuario conjuntamente con PHP tardara unos segundos más en verificar la contraseña cifrada.
Cifrar contraseñas usando PHP PDO: Procesos
A continuación, veremos un ejemplo completo de registro y login.
- Cifrar contraseña mediante PDO con hash
- Almacenar la contraseña cifrada en MySQL
- Comprobar la clave del usuario al iniciar sesión mediante PDO
- Realizar una consulta SQL con PDO con un usuario existente
1) Crear usuario y cifrar contraseña con PDO
Primeramente, crear una base de datos en Workbench o en phpMyAdmin, por ejemplo, que sea llamada cifrado_php y dentro una tabla llamada personal a la que le hemos creado 6 campos que son los siguientes:
`idp`, `nombre`, `apellidos`, `cargo`, `password`, `genero`
Tabla Personal
CREATE TABLE `personal` ( `idp` int(11) NOT NULL, `nombre` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `apellidos` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `cargo` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `password` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `genero` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ALTER TABLE `personal` ADD PRIMARY KEY (`idp`); ALTER TABLE `personal` MODIFY `idp` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
2) Crear fichero de conexión
Este fichero será el más importante porque su rol será de conectar PHP con el gestor de base de datos. Sin embargo, para este ejemplo lo llamaremos dbc.php
Aquí, se creará el objeto PDO con la conexión y nos permitirá la inserción a la base de datos, modificación, consulta de registros y eliminación de registros, es decir un CRUD PHP.
<?php //configuracion de la conexion $servidor = 'localhost'; $BD = 'cifrado_php'; $usuario = 'root'; $password = ''; //establezco la conexion con PDO en este caso para MySQL u otro gestor $DB = new PDO("mysql:host=$servidor; dbname=$BD", $usuario, $password); //aplico el cotejamiento $DB->exec("SET CHARACTER SET utf8"); ?>
3) Crear formulario de registro
Para poder registrar un personal tenemos que tener un formulario. Para este ejemplo, lo llamaremos registro.php, nos mostrara un sencillo formulario con varios campos usando librería BootStrap para darle una interfaz amigable.
<h3>Registrar personal</h3> <form action="guarda_registro.php" method="post"> <div class="form-group"> <label for="email">Nombre:</label> <input name="nombre" required type="text" class="form-control" placeholder="Nombre"> </div> <div class="form-group"> <label for="apellidos">Apellidos:</label> <input name="apellidos" required type="text" class="form-control" placeholder="Apellidos"> </div> <div class="form-group"> <label for="email">Cargo:</label> <select required name="cargo" class="form-control"> <option value=""><< Seleccioe >></option> <option value="Administrador">Administrador</option> <option value="Contador">Contador</option> <option value="Secretaria">Secretaria</option> <option value="Gerente">Gerente</option> <option value="Sistemas">Sistemas</option> </select> </div> <div class="form-group"> <label for="email">Contraseña:</label> <input name="password" required type="password" class="form-control" placeholder="Password"> </div> <div class="form-group"> <label for="email">Genero:</label> <select required name="genero" class="form-control"> <option value=""><< Seleccione >></option> <option value="M">Masculino</option> <option value="F">Femenino</option> </select> </div> <button class="btn btn-primary">Registrar personal</button> </form>
4) Almacenar datos del formulario
El fichero lo llamaremos guarda_registro.php y será el encargado de guardar la información del formulario a la base de datos. Además, de cifrar la contraseña con la función password_hash
y un nivel de cost.
<?php require 'dbc.php'; //antes de nada obtengo la contraseña y la cifro para insertarla $password = $_POST['password']; //y ahora cifro la clave usando un hash $pass_cifrada = password_hash($password, PASSWORD_DEFAULT, array("cost"=>10)); if ($DB == true) { //preparo el insert $insert = $DB->prepare("INSERT INTO personal (nombre, apellidos, cargo, password, genero) VALUES (:nombre, :apellidos, :cargo, :password, :genero)"); //asocio los campos del insert a los campos del formulario $insert->bindParam(':nombre', $_POST['nombre']); $insert->bindParam(':apellidos', $_POST['apellidos']); $insert->bindParam(':cargo', $_POST['cargo']); $insert->bindParam(':password', $pass_cifrada); $insert->bindParam(':genero', $_POST['genero']); //ejecutamos codigo anterior $insert->execute(); //cierramos la conexion $DB = null; //redirijo a un archivo php header('Location: index.php'); } else { echo "Error al procesar recurso"; } ?>
5) Login de usuario con clave cifrada
En este paso usaremos un fichero con el nombre de login.php y será el encargado de recoger el nombre y la contraseña que será procesada posteriormente.
Por lo tanto, este fichero realizara el rol de verificar los datos ingresados por el usuario final.
<h2>Login de usuarios</h2> <p>Acceso de Personal</p> <form action="verifica.php" method="post"> <div class="form-group"> <label for="Nombre">Nombre:</label> <input name="nombre" required type="text" class="form-control" placeholder="Nombre" autocomplete="off"> </div> <div class="form-group"> <label for="Password">Password:</label> <input name="password" required type="password" class="form-control" placeholder="Password" autocomplete="off"> </div> <button class="btn btn-primary">Acceder</button> </form>
Sin embargo, este formulario enviará los datos al fichero con nombre verifica.php, este archivo recibirá la contraseña tipo texto sin cifrar y haciendo uso de la función password_verify podemos ver si coincide con la contraseña cifrada en la base de datos.
Si la contraseña es idéntica, se podrá crear sesiones y redirecciones en nuestro sistema web.
<?php require 'dbc.php';
try { //verifico los datos del login $nombre=htmlentities(addslashes($_POST['nombre'])); $password=htmlentities(addslashes($_POST['password']));//variable auxiliar para comprobar que el usuario existe o no $contador = 0;//almaceno la consulta SQL en una variable $sql = "SELECT * FROM personal WHERE nombre = :nombre"; //preparo la consulta SQL $resultado=$DB->prepare($sql); //ejecucion de la consulta $resultado->execute(array(":nombre"=>$nombre)); //resultado en un array asociativo tipo while while($login=$resultado->fetch(PDO::FETCH_ASSOC)) { if(password_verify($password, $login['password'])) { /* aqui se podra crear sesiones */ $contador++; } } if ($contador>0) { echo "el usuario existe"; } else { echo "el usuario no existe"; } //cierro la conexion $conexion = null; } catch(Exception $e) { die($e->getMessage()); } ?>
6) Crear consultas con PHP PDO
El último paso sería visualizar los usuarios registrados haciendo uso de consultas PHP y usaremos un archivo llamado index.php
<?php require 'dbc.php'; //preparo una consulta SQL $sql = "SELECT * FROM personal"; //almaceno el restulado en una variable $resultado = $DB->query($sql); ?> <!doctype html> <html lang="es"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>Cifrado de contraseñas | BaulPHP</title> <!-- Bootstrap core CSS --> <link href="dist/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom styles for this template --> <link href="dist/css//sticky-footer-navbar.css" rel="stylesheet"> </head> <body> <header> <!-- Fixed navbar --> <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark"> <a class="navbar-brand" href="#">BaulPHP</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarCollapse"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="index.php">Inicio <span class="sr-only">(current)</span></a> </li> <li class="nav-item active"> <a class="nav-link" href="registro.php">Registro </a> </li> <li class="nav-item active"> <a class="nav-link" href="login.php">Acceso </a> </li> </ul> <form class="form-inline mt-2 mt-md-0"> <input class="form-control mr-sm-2" type="text" placeholder="Buscar" aria-label="Search"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Busqueda</button> </form> </div> </nav> </header> <!-- Begin page content --> <div class="container"> <div class="row"> <div class="col-12 col-md-12"> <!-- Contenido --> <h2>Lista de Empleados</h2> <p>Area administrativa</p> <table class="table table-striped"> <thead> <tr> <th>Id</th> <th>Nombre</th> <th>Apellidos</th> <th>Cargo</th> <th>Password</th> <th>Genero</th> </tr> </thead> <tbody> <?php //recorro toda la consulta foreach($resultado as $fila) { echo "<tr>"; echo "<td>".$fila['idp']."</td>"; echo "<td>".$fila['nombre']."</td>"; echo "<td>".$fila['apellidos']."</td>"; echo "<td>".$fila['cargo']."</td>"; echo "<td>******</td>"; echo "<td>".$fila['genero']."</td>"; echo "</tr>"; } ?> </tbody> </table> <!-- Fin Contenido --> </div> </div> <!-- Fin row --> </div> <!-- Fin container --> <footer class="footer"> <div class="container"> <span class="text-muted"> <p>Códigos <a href="https://www.baulphp.com/" target="_blank">BaulPHP</a></p> </span> </div> </footer> <!-- Bootstrap core JavaScript ================================================== --> <script src="dist/js/jquery-1.12.4-jquery.min.js"></script> <script src="dist/js/bootstrap.min.js"></script> <!-- Placed at the end of the document so the pages load faster --> </body> </html>
CONCLUSION: Cifrar contraseñas usando PHP
De una manera simple podemos agregar PDO y cifrar las contraseñas de nuestros sistemas desarrollados con PHP.
Hemos aprendido a cifrar contraseñas y comparar si son idénticas a la base de datos usando la función password_verify del PHP
Con esto ya tienes un sistema de login fácil y escalable y con un método más fuerte de cifrado que contiene PHP.
DESCARGAR CODIGO FUENTE
[sociallocker id=5099]Descargar sistema cifrar contraseñas PHP PDO
Hola Nestor:
Muy bueno tu tutorial. Mi problema es que me verifica perfectamente pero solo puedo crear la sesion de nombre y password pero no soy capaz de crear sesiones de los demás datos.
Dandote las gracias por anticipado, quedo a la espera de tus noticias.
Excelente Nestor, saludos!
Hola Nestor:
Observo que al entrar al logín, se lanza un mensaje de que sí o no está el usuario, pero no me retorna a ninguna parte. Si el usuario existe, no debería volver al inicio? Y si no existe, no debería volver al formulario para inserción de usuarios?
Saludos!