Sistema de restablecimiento de contraseña en PHP

Una característica muy importante de cualquier buen sitio web de membresía es un sistema de restablecimiento de contraseña porque algunos usuarios están obligados a olvidar su contraseña. En este tutorial, describo los pasos necesarios para recuperar la contraseña de un usuario; también implementaremos dicho sistema usando PHP y una base de datos MySQL en este tutorial.

Todo el proceso de implementación de un sistema de este tipo se puede dividir en 3 pasos principales. Para facilitar la explicación, analicemos estos pasos en cuanto a los formularios que presentaremos para que el usuario los llene:

  1. Formulario de inicio de sesión: Este formulario toma la combinación de nombre de usuario y contraseña de un usuario y lo registra si está registrado en el sistema. En este formulario proporcionamos un “¿Olvidó su contraseña?” enlace en caso de que el usuario haya olvidado su contraseña y necesite restablecerla.
  2. Formulario de correo electrónico: Si el usuario ha olvidado su contraseña, puede hacer clic en “¿Olvidó su contraseña?” enlace en la página de inicio de sesión para restablecerlo. Al hacer clic en este enlace, los llevará a otra página que les pedirá que ingresen el correo electrónico. Cuando la dirección de correo electrónico que proporcionan no está en nuestro usuarios tabla en la base de datos, mostraremos un mensaje de error que dice “No existe tal usuario en nuestro sistema”. Si, por otro lado, el usuario existe, generaremos un token único (una cadena aleatoria única) y almacenaremos este token junto con esa dirección de correo electrónico en el password_resets tabla en la base de datos. Luego les enviaremos un correo electrónico que tenga ese token en un enlace. Cuando hagan clic en el enlace del correo electrónico que les enviamos, serán enviados de vuelta a nuestro sitio web en una página que les presenta otro formulario.
  3. Formulario de nueva contraseña: Una vez que el usuario vuelva a nuestro sitio web, tomaremos el token que proviene del enlace y lo almacenaremos en una variable de sesión. Luego les presentaremos un formulario que les pedirá que ingresen una nueva contraseña para su cuenta en nuestro sitio web. Cuando se envíe la nueva contraseña, consultaremos el password_resets tabla para el registro que tiene ese token que acaba de llegar desde el enlace en el correo. Si el token se encuentra en el password_resets , entonces estamos seguros de que el usuario es quien es y que hizo clic en el enlace de su correo. En este punto, ahora tomamos el correo electrónico del usuario del password_resets (recuerde que habíamos guardado el token junto con su dirección de correo electrónico) y use ese correo electrónico para buscar al usuario de la tabla de usuarios y actualizar su contraseña.

Espero que sea lo suficientemente claro. Si no es así, quédese y se volverá más claro a medida que lo implementemos.

Implementación

Crea una base de datos llamada recuperación de contraseña y en esa base de datos, cree dos tablas a saber usuarios y password_resets con los siguientes campos:

usuarios:

+----+-----------+--------------+------------+
|     field      |     type     | specs      |
+----+-----------+--------------+------------+
|  id            | INT(11)      |            |
|  username      | VARCHAR(255) |            |
|  email         | VARCHAR(255) | UNIQUE     |
|  password      | VARCHAR(255) |            |
+----------------+--------------+------------+

password_resets:

+----+-----------+--------------+------------+
|     field      |     type     | specs      |
+----+-----------+--------------+------------+
|  id            | INT(11)      |            |
|  email         | VARCHAR(255) |            |
|  token         | VARCHAR(255) | UNIQUE     |
+----------------+--------------+------------+

Notas: Esta aplicación requiere que el usuario ya esté registrado en el sistema. Pero, no cubriremos la parte de registro de usuario en este tutorial porque ya se ha cubierto en este sitio. Puede seguir ese tutorial primero (le recomiendo que lo haga) o no, pero tenga en cuenta que necesitamos tener un usuario en nuestra tabla de usuarios en la base de datos antes de que podamos proceder a restablecer su contraseña. Entonces, de una forma u otra, agregue un usuario a su base de datos mysql. Puede usar una herramienta como PHPMyAdmin y asegurarse de encriptar la contraseña usando md5 ().

Ahora crea una carpeta de proyecto llamada recuperación de contraseña y asegúrese de que esta carpeta esté en el directorio de su servidor (htdocs carpeta o www carpeta). En esa carpeta, cree tres archivos a saber: login.php, enter_email.php, new_pass.php:

Cada uno de estos tres archivos representa los tres pasos que describimos anteriormente. Abra cada uno de ellos y pegue los siguientes códigos en ellos:

login.php:

<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Password Reset PHP</title>
	<link rel="stylesheet" href="main.css">
</head>
<body>
	<form class="login-form" action="login.php" method="post">
		<h2 class="form-title">Login</h2>
		<!-- form validation messages -->
		<?php include('messages.php'); ?>
		<div class="form-group">
			<label>Username or Email</label>
			<input type="text" value="<?php echo $user_id; ?>" name="user_id">
		</div>
		<div class="form-group">
			<label>Password</label>
			<input type="password" name="password">
		</div>
		<div class="form-group">
			<button type="submit" name="login_user" class="login-btn">Login</button>
		</div>
		<p><a href="enter_email.php">Forgot your password?</a></p>
	</form>
</body>
</html>

enter_email.php:

<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Password Reset PHP</title>
	<link rel="stylesheet" href="main.css">
</head>
<body>
	<form class="login-form" action="enter_email.php" method="post">
		<h2 class="form-title">Reset password</h2>
		<!-- form validation messages -->
		<?php include('messages.php'); ?>
		<div class="form-group">
			<label>Your email address</label>
			<input type="email" name="email">
		</div>
		<div class="form-group">
			<button type="submit" name="reset-password" class="login-btn">Submit</button>
		</div>
	</form>
</body>
</html>

new_pass.php:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Password Reset PHP</title>
	<link rel="stylesheet" href="main.css">
</head>
<body>
	<form class="login-form" action="new_password.php" method="post">
		<h2 class="form-title">New password</h2>
		<!-- form validation messages -->
		<?php include('messages.php'); ?>
		<div class="form-group">
			<label>New password</label>
			<input type="password" name="new_pass">
		</div>
		<div class="form-group">
			<label>Confirm new password</label>
			<input type="password" name="new_pass_c">
		</div>
		<div class="form-group">
			<button type="submit" name="new_password" class="login-btn">Submit</button>
		</div>
	</form>
</body>
</html>

En cada uno de estos archivos, verá que incluimos tres archivos que aún no hemos creado, a saber, el app_logic.php , messages.php, archivo y main.css. El primero maneja toda la lógica de nuestra aplicación como consultar la base de datos, enviar correo electrónico al usuario y más; el segundo muestra mensajes de retroalimentación al usuario, como cuando ingresan un correo electrónico incorrecto, el tercero es el estilo de la aplicación.

Cree estos archivos en la carpeta de recuperación de contraseña. En el archivo main.css, agregue este código de estilo:

main.css:

body {
	background: #3b5998;
	font-size: 1.1em;
	font-family: sans-serif;
}
a {
	text-decoration: none;
}
form {
	width: 25%;
	margin: 70px auto;
	background: white;
	padding: 10px;
	border-radius: 3px;
}
h2.form-title {
	text-align: center;
}
input {
	display: block;
	box-sizing: border-box;
	width: 100%;
	padding: 8px;
}
form .form-group {
	margin: 10px auto;
}
form button {
	width: 100%;
	border: none;
	color: white;
	background: #3b5998;
	padding: 15px;
	border-radius: 5px;
}
.msg {
	margin: 5px auto;
	border-radius: 5px;
	border: 1px solid red;
	background: pink;
	text-align: left;
	color: brown;
	padding: 10px;
}

app_logic.php:

<?php 

session_start();
$errors = [];
$user_id = "";
// connect to database
$db = mysqli_connect('localhost', 'root', '', 'password-reset-php');

// LOG USER IN
if (isset($_POST['login_user'])) {
  // Get username and password from login form
  $user_id = mysqli_real_escape_string($db, $_POST['user_id']);
  $password = mysqli_real_escape_string($db, $_POST['password']);
  // validate form
  if (empty($user_id)) array_push($errors, "Username or Email is required");
  if (empty($password)) array_push($errors, "Password is required");

  // if no error in form, log user in
  if (count($errors) == 0) {
    $password = md5($password);
    $sql = "SELECT * FROM users WHERE username='$user_id' OR email='$user_id' AND password='$password'";
    $results = mysqli_query($db, $sql);

    if (mysqli_num_rows($results) == 1) {
      $_SESSION['username'] = $user_id;
      $_SESSION['success'] = "You are now logged in";
      header('location: index.php');
    }else {
      array_push($errors, "Wrong credentials");
    }
  }
}

/*
  Accept email of user whose password is to be reset
  Send email to user to reset their password
*/
if (isset($_POST['reset-password'])) {
  $email = mysqli_real_escape_string($db, $_POST['email']);
  // ensure that the user exists on our system
  $query = "SELECT email FROM users WHERE email='$email'";
  $results = mysqli_query($db, $query);

  if (empty($email)) {
    array_push($errors, "Your email is required");
  }else if(mysqli_num_rows($results) <= 0) {
    array_push($errors, "Sorry, no user exists on our system with that email");
  }
  // generate a unique random token of length 100
  $token = bin2hex(random_bytes(50));

  if (count($errors) == 0) {
    // store token in the password-reset database table against the user's email
    $sql = "INSERT INTO password_reset(email, token) VALUES ('$email', '$token')";
    $results = mysqli_query($db, $sql);

    // Send email to user with the token in a link they can click on
    $to = $email;
    $subject = "Reset your password on examplesite.com";
    $msg = "Hi there, click on this <a href="new_password.php?token=" . $token . "">link</a> to reset your password on our site";
    $msg = wordwrap($msg,70);
    $headers = "From: info@examplesite.com";
    mail($to, $subject, $msg, $headers);
    header('location: pending.php?email=' . $email);
  }
}

// ENTER A NEW PASSWORD
if (isset($_POST['new_password'])) {
  $new_pass = mysqli_real_escape_string($db, $_POST['new_pass']);
  $new_pass_c = mysqli_real_escape_string($db, $_POST['new_pass_c']);

  // Grab to token that came from the email link
  $token = $_SESSION['token'];
  if (empty($new_pass) || empty($new_pass_c)) array_push($errors, "Password is required");
  if ($new_pass !== $new_pass_c) array_push($errors, "Password do not match");
  if (count($errors) == 0) {
    // select email address of user from the password_reset table 
    $sql = "SELECT email FROM password_reset WHERE token='$token' LIMIT 1";
    $results = mysqli_query($db, $sql);
    $email = mysqli_fetch_assoc($results)['email'];

    if ($email) {
      $new_pass = md5($new_pass);
      $sql = "UPDATE users SET password='$new_pass' WHERE email='$email'";
      $results = mysqli_query($db, $sql);
      header('location: index.php');
    }
  }
}
?>

Aquí ves tres bloques de Si declaraciones. Estas declaraciones manejan tres acciones, a saber, el inicio de sesión del usuario, la recepción de un correo electrónico de restablecimiento y la recepción de una nueva contraseña. En el segundo bloque, después de recibir la dirección de correo electrónico del usuario, el usuario es redirigido a una página pendiente.php. Esta página simplemente muestra un mensaje que le dice al usuario que se ha enviado un correo electrónico a su dirección de correo electrónico que puede usar para restablecer su contraseña.

Cree pendiente.php en la carpeta raíz de nuestro proyecto y agregue este código dentro de él:

pendiente.php:

<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Password Reset PHP</title>
	<link rel="stylesheet" href="main.css">
</head>
<body>

	<form class="login-form" action="login.php" method="post" style="text-align: center;">
		<p>
			We sent an email to  <b><?php echo $_GET['email'] ?></b> to help you recover your account. 
		</p>
	    <p>Please login into your email account and click on the link we sent to reset your password</p>
	</form>
		
</body>
</html>

messages.php es un archivo que contiene el fragmento de código para mostrar mensajes de error en el formulario. Ábrelo y pega este código en su interior:

messages.php:

<?php  if (count($errors) > 0) : ?>
  <div class="msg">
  	<?php foreach ($errors as $error) : ?>
  	  <span><?php echo $error ?></span>
  	<?php endforeach ?>
  </div>
<?php  endif ?>

Ahora abra este proyecto en su navegador en http: //localhost/password-recovery/login.php y juegue con él.

Notas: Usamos la función mail () de PHP para enviar correos electrónicos al usuario. Esta función no puede enviar correos desde localhost. Solo puede hacerlo mediante un servidor alojado en Internet. Sin embargo podemos utilizar una aplicación de correo de prueba para simular el envío de correos electrónicos si desea tener una demostración en su sistema local.

Conclusión

Gracias por seguir este tutorial hasta el final. Espero que la explicación haya sido lo suficientemente clara y hayas aprendido algo que te pueda ayudar en tu desarrollo web. Si tiene algún problema o inquietud, no olvide dejarlo en los comentarios a continuación y me comunicaré con usted.

¡Que tenga un lindo día!

Awa Melvine

Deja un comentario