1. Code
  2. PHP

Cómo construir un sistema de inicio de sesión con todas las funciones

Scroll to top

Spanish (Español) translation by Luis Chiabrera (you can also view the original English article)

En este tutorial, le mostraré cómo hacer un sistema de inicio de sesión simple que consiste en una página de inicio de sesión, una página de registro, una página de contraseña olvidada, una activación de correo electrónico, una página de cierre de sesión y, finalmente, una página de usuarios en línea. Hice este tutorial para dirigirse principalmente a los desarrolladores de PHP nuevos, ya que cuando comencé noté la falta de cantidad de sistemas de inicio de sesión básicos. Por lo tanto, ¡decidí hacer uno mismo para dar consejos de alta calidad sobre cómo hacer su primer sistema de inicio de sesión con un script en línea para usuarios!


1. Hacer una hoja de estilo básica

Vamos a crear una hoja de estilo CSS muy básica solo para agregar un poco de diseño y ordenar el aspecto del sistema de inicio de sesión. Así que empieza con el editor de texto abierto y podemos comenzar a hacer nuestra hoja de ruta.

1
body { font-family: arial; font-size: 10pt; } table { font-size: 10pt; margin: 0 auto; } #border { border: 2px solid #999; background: #CCC; 
2
padding: 15px; margin: 0 auto; width: 300px; }

Guarde este archivo como style.css para que podamos vincularlo cuando lo necesitemos. Ahí tenemos nuestra simple hoja de estilo! Ahora podemos comenzar a hacer nuestras páginas sin tener que preocuparnos demasiado por hacer que se vean razonablemente bien.



2. Creando la página de inicio de sesión

De acuerdo, tenemos una hoja de estilo definida, ahora es el momento de mostrar las cosas en nuestras páginas. Abra un nuevo archivo en su editor de texto, ¡esta será nuestra página login.php!

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 <form action="login.php" method="post"> <div id="border"> <table border="0" cellpadding="2" cellspacing="0"> <tbody><tr> <td>Username:</td> <td><input name="username" type="text"></td> </tr> 
4
<tr> <td>Password:</td> <td><input name="password" type="password"></td> </tr> <tr> <td colspan="2" align="center"><input name="submit" value="Login" type="submit"></td> </tr> <tr> <td 
5
colspan="2" align="center"><a href="register.php">Register</a> | <a href="forgot.php">Forgot Pass</a></td> </tr> </tbody></table> </div> </form>

Bien, este es el aspecto que tendrá nuestro archivo login.php antes de que obtengamos nuestro PHP que hace funcionar correctamente el formulario de inicio de sesión. En el momento te darás cuenta de que no funciona. Esto se debe a que no le hemos dicho a la página qué hacer si se envía el formulario.

Planificación

Ahora hagamos un poco de planificación antes de sumergirnos en el PHP. Necesitamos preguntarnos "¿Qué va a revisar la página cuando se envíe el formulario?". Para la página de inicio de sesión aquí hay una lista de lo que vamos a revisar -

  • Que tanto el usuario como la contraseña han sido rellenados
  • Que el nombre de usuario suministrado existe en nuestra base de datos.
  • Que si el nombre de usuario existe en nuestra base de datos, la contraseña coincide con la del nombre de usuario.
  • Finalmente, que el usuario ha activado su cuenta.

Si el PHP puede responder sí a los cuatro puntos, inicie sesión en el usuario. Ahora, en esos cuatro puntos, notará que se mencionó una base de datos. Vamos a utilizar una base de datos MySQL para almacenar toda la información sobre cada uno de nuestros usuarios. Así que antes de comenzar con PHP necesitamos hacer esta base de datos. En este punto se necesita un poco más de planificación. Necesitamos decidir qué información necesitamos almacenar sobre los usuarios, qué tipos de datos estamos almacenando, necesitamos un valor predeterminado, etc. Aquí está mi plan a continuación:

  • Necesitamos almacenar un nombre de usuario para el usuario que será un varchar
  • Necesitamos una contraseña para que también sea una varchar.
  • Necesitaremos un correo electrónico para nuestra función de activación de correo electrónico, esto también puede ser varchar
  • Un campo que indica si la cuenta se ha activado o no, será un número entero.
  • Un campo que proporciona información sobre si el usuario está en línea o no, este será un número entero
  • Finalmente, un campo que nos da una hora en que el usuario se registró, este también es un número entero.

Construyendo la base de datos

Ahora de esto podemos ver exactamente cómo construir nuestra tabla en nuestra base de datos. Primero crea una base de datos llamada loginTut. Luego, en esta base de datos, queremos ejecutar el SQL que he proporcionado a continuación:

Nota: Todas las tablas contienen una clave primaria. ¡Este es un identificador único para cada fila en la tabla!

1
CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL auto_increment, `username` varchar(32) NOT NULL, `password` varchar(32) NOT NULL, 
2
`online` int(20) NOT NULL default 0', `email` varchar(100) NOT NULL, `active` int(1) NOT NULL default ‘0', `rtime` int(20) NOT NULL default 0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT 

3
CHARSET=utf8;

Ahora que tenemos una tabla para almacenar toda la información que necesitamos sobre nuestros usuarios, agreguemos un usuario para fines de prueba. Para hacer esto ejecute el SQL que se proporciona a continuación:

1
INSERT INTO `users` (`id`, `username`, `password`, `online`, `email`, `active`, `rtime`) VALUES (1, testing, testing, 0, 
2
fake@noemail.co.uk, 0, 0);

Así que ahora tenemos un usuario con la prueba de nombre de usuario, la prueba de contraseña y el correo electrónico fake@noemail.co.uk. ¡Ahora podemos acceder al PHP y hacer que el formulario de inicio de sesión funcione!

Añadiendo el PHP

Lo primero es lo primero que tenemos que pensar sobre la seguridad y qué tan seguro será este formulario de inicio de sesión. Para ayudar a prevenir la inyección SQL, que es una forma muy común de pirateo de bases de datos, vamos a realizar una función que protegerá todas las cadenas almacenadas en la base de datos. Esto lo pondremos en un archivo externo llamado functions.php. Aquí está la fuente:

1
 <?php 
2
 
3
function protect($string){ $string = trim(strip_tags(addslashes($string))); return $string; } 
4
 
5
?>

Esta función recortará nuestra cadena (cortará cualquier espacio en blanco al principio o al final de la cadena), eliminará las etiquetas (eliminará todas las etiquetas html y PHP de la cadena) y luego agregará barras diagonales a la cadena que escapa las marcas de voz (') y comillas (").

Volver a login.php

Ahora tenemos un lugar para almacenar y verificar la información del usuario, una función para proteger las cadenas que se pasan a la base de datos, y un diseño atractivo para nuestra página de inicio de sesión. A continuación puede ver el código comentado para nuestro archivo login.php con el nuevo PHP agregado

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 You need to fill in a <strong>Username</strong> and a <strong>Password</strong>!"; }else{ //if the were continue checking 
4
 
5
 //select all rows from the table where the username matches the one entered by the user $res = mysql_query("SELECT * FROM `users` WHERE `username` = '".$username."'"); $num = 
6
mysql_num_rows($res); 
7
 
8
 //check if there was not a match if($num == 0){ //if not display an error message echo "<center>The <strong>Username</strong> you supplied does not exist!</center>"; }else{ //if there was a match 
9
continue checking 
10
 
11
 //select all rows where the username and password match the ones submitted by the user $res = mysql_query("SELECT * FROM `users` WHERE `username` = '".$username."' AND `password` = 
12
'".$password."'"); $num = mysql_num_rows($res); 
13
 
14
 //check if there was not a match if($num == 0){ //if not display error message echo "<center>The <strong>Password</strong> you supplied does not match the one for that username!</center>"; }else{ //if 
15
there was continue checking 
16
 
17
 //split all fields fom the correct row into an associative array $row = mysql_fetch_assoc($res); 
18
 
19
 //check to see if the user has not activated their account yet if($row['active'] != 1){ //if not display error message echo "<center>You have not yet <strong>Activated</strong> your account!</center>"; 
20
}else{ //if they have log them in 
21
 
22
 //set the login session storing there id - we use this to see if they are logged in or not $_SESSION['uid'] = $row['id']; //show message echo "<center>You have successfully logged 
23
in!</center>"; 
24
 
25
 //update the online field to 50 seconds into the future $time = date('U')+50; mysql_query("UPDATE `users` SET `online` = '".$time."' WHERE `id` = '".$_SESSION['uid']."'"); 
26
 
27
 //redirect them to the usersonline page header('Location: usersOnline.php'); } } } } } 
28
 
29
 ?> <form action="login.php" method="post"> <div id="border"> <table border="0" cellpadding="2" cellspacing="0"> <tbody><tr> <td>Username:</td> <td><input name="username" type="text"></td> 
30
</tr> <tr> <td>Password:</td> <td><input name="password" type="password"></td> </tr> <tr> <td colspan="2" align="center"><input name="submit" value="Login" type="submit"></td> </tr> <tr> <td 
31
colspan="2" align="center"><a href="register.php">Register</a> | <a href="forgot.php">Forgot Pass</a></td> </tr> </tbody></table> </div> </form>

La mayor parte de esto se explica por los comentarios, pero una parte que no expliqué es el campo en línea. Cuando inicie sesión con éxito, actualizamos el campo en línea a 50 segundos antes de ahora. La función de fecha ('U') nos da la cantidad de segundos desde el 1 de enero de 1970 a las 00:00:00 GMT (época de Unix). Esto significa que la fecha ('U') nunca se reducirá, el valor siempre aumentará. Si configuramos el campo en línea con 50 segundos de anticipación, entonces, cuando se carga la página de Usuarios en línea, podemos verificar para encontrar a todos los usuarios en los que el valor en línea sea mayor que el momento en que se cargó la página, si este es el caso, se mostrará cada uno de sus nombres.

Ahora siéntase libre de probar su página de inicio de sesión. Asegúrese de que todas las comprobaciones se realicen correctamente y de que, una vez que haya iniciado sesión correctamente, se le redirija a la página en línea de usuarios no existentes. ¡También puede verificar si ha actualizado exitosamente el campo en línea revisando la tabla de usuarios!



3. Creando la página de registro

¿De qué sirve una página de inicio de sesión sin una página de registro? No mucho en absoluto, así que creo que ese será el próximo paso que debemos tomar. Crear la página de registro será muy similar a crear nuestra página de inicio de sesión. Necesitamos hacer una comprobación básica para ver si el nombre de usuario deseado ya está tomado, pero no hay nada nuevo sucediendo allí. Abajo puede ver el código de la página de registro comentada -

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 You need to fill in all of the required filds!"; }else{ //if all were filled in continue checking 
4
 
5
 //Check if the wanted username is more than 32 or less than 3 charcters long if(strlen($username) > 32 || strlen($username) < 3){ //if it is display error message echo "<center>Your <strong>Username</strong> must be between 3 and 32 characters long!</center>"; }else{ //if not continue checking 
6
 
7
 //select all the rows from out users table where the posted username matches the username stored $res = mysql_query("SELECT * FROM `users` WHERE `username` = '".$username."'"); $num = 
8
mysql_num_rows($res); 
9
 
10
 //check if theres a match if($num == 1){ //if yes the username is taken so display error message echo "<center>The <strong>Username</strong> you have chosen is already taken!</center>"; }else{ 
11
//otherwise continue checking 
12
 
13
 //check if the password is less than 5 or more than 32 characters long if(strlen($password) < 5 || strlen($password) > 32){ //if it is display error message echo "<center>Your <strong>Password</strong> must be between 5 and 32 characters long!</center>"; }else{ //else continue checking 
14
 
15
 //check if the password and confirm password match if($password != $passconf){ //if not display error message echo "<center>The <strong>Password</strong> you supplied did not match the confirmation password!</center>"; }else{ //otherwise continue checking 
16
 
17
 //Set the format we want to check out email address against $checkemail = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i"; 
18
 
19
 //check if the formats match if(!preg_match($checkemail, $email)){ //if not display error message echo "<center>The <strong>E-mail</strong> is not valid, must be name@server.tld!</center>"; }else{ //if they do, continue checking 
20
 
21
 //select all rows from our users table where the emails match $res1 = mysql_query("SELECT * FROM `users` WHERE `email` = '".$email."'"); $num1 = mysql_num_rows($res1); 
22
 
23
 //if the number of matchs is 1 if($num1 == 1){ //the email address supplied is taken so display error message echo "<center>The <strong>E-mail</strong> address you supplied is already taken</center>"; 
24
}else{ //finally, otherwise register there account 
25
 
26
 //time of register (unix) $registerTime = date('U'); 
27
 
28
 //make a code for our activation key $code = md5($username).$registerTime; 
29
 
30
 //insert the row into the database $res2 = mysql_query("INSERT INTO `users` (`username`, `password`, `email`, `rtime`) 
31
VALUES('".$username."','".$password."','".$email."','".$registerTime."')"); 
32
 
33
 //send the email with an email containing the activation link to the supplied email address mail($email, $INFO['chatName'].' registration confirmation', "Thank you for registering to us".$username.",\n\nHere is your activation link. If the link doesn't work copy and paste it into your browser address bar.\n\nhttps://www.yourwebsitehere.co.uk/activate.php?code=".$code, 'From:noreply@youwebsitehere.co.uk'); 
34
 
35
 //display the success message echo "<center>You have successfully registered, please visit you inbox to activate your account!</center>"; } } } } } } } } 
36
 
37
 ?> <div id="border"> <form action="register.php" method="post"> <table border="0" cellpadding="2" cellspacing="0"> <tbody><tr> <td>Username: </td> <td><input name="username" type="text"></td> 
38
</tr> <tr> <td>Password: </td> <td><input name="password" type="password"></td> </tr> <tr> <td>Confirm Password: </td> <td><input name="passconf" type="password"></td> </tr> <tr> <td>Email: 
39
</td> <td><input name="email" size="25" type="text"></td> </tr> <tr> <td colspan="2" align="center"><input name="submit" value="Register" type="submit"></td> </tr> <tr> <td colspan="2" 
40
align="center"><a href="login.php">Login</a> | <a href="forgot.php">Forgot Pass</a></td> </tr> </tbody></table> </form> </div>

Nuevas funciones

Este archivo contiene algunas cosas nuevas con las que quizás no esté familiarizado, por lo tanto, revisaré todo. En primer lugar, la función strlen (), esto devuelve el número de caracteres en una cadena que nos permite verificar cuánto tiempo son las cadenas. Luego, la función preg_match () comprueba si el formato de una cadena coincide con el formato que especifique (en este caso es un formato de correo electrónico). Finalmente, la función de correo () envía un correo electrónico desde el servidor a cualquier correo electrónico de su elección que contenga lo que desee. Debes guardar este archivo como register.php

Ahora puede probar su página de registro, puede ver que cuando ingrese su dirección de correo electrónico correcta recibirá un correo electrónico con un enlace de activación contenido en su interior. También puede ver que una fila que contiene los datos rellenados en el formulario se ingresa en la tabla de usuarios. El valor de activo es 0, lo que demuestra que esta cuenta aún no se ha activado.



4. Active la página de su cuenta

Esta es solo una página pequeña con muy poco código requerido, pero aún así es muy importante y juega un papel muy importante en un sistema de inicio de sesión seguro. La fuente de esta página se muestra a continuación: enable.php

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 Unfortunatly there was an error there!"; }else{ //other wise continue the check 
4
 
5
 //select all the rows where the accounts are not active $res = mysql_query("SELECT * FROM `users` WHERE `active` = '0'"); 
6
 
7
 //loop through this script for each row found not active while($row = mysql_fetch_assoc($res)){ //check if the code from the row in the database matches the one from the user if($code == md5($row['username']).$row['rtime']){ //if it does then activate there account and display success message $res1 = mysql_query("UPDATE `users` SET `active` = '1' WHERE `id` = '".$row['id']."'"); echo "<center>You have successfully activated your account!</center>"; } } } 
8
 
9
 ?>

Hay dos cosas nuevas en este archivo, usamos el método GET en lugar de POST y también usamos un ciclo while (). El método de obtención simplemente obtiene datos de la barra de direcciones en la parte superior del navegador del usuario (en este caso, el código enviado con el correo electrónico a su dirección de correo electrónico). El bucle while () es perfecto para verificar a través de múltiples filas de datos seleccionados de la base de datos (en este caso, para ver si hay una coincidencia con los códigos).

Visión general hasta ahora

Hasta ahora, debería haber aprendido muchas cosas nuevas si es nuevo en PHP y ha creado con éxito la mitad de un sistema de inicio de sesión. Las páginas completadas hasta ahora son:

  • style.css
  • functions.php
  • login.php
  • register.php
  • activate.php

Algunas funciones útiles utilizadas hasta ahora son:

  • mysql_connect (): conectarse a una base de datos mysql
  • mysql_select_db (): seleccione la base de datos con la que deberíamos trabajar
  • mysql_query (): envíe consultas a la base de datos para obtener, insertar o editar datos
  • recortar (): corta el espacio en blanco no deseado del principio y final de una cuerda
  • strip_tags (): elimina las etiquetas html y PHP de una cadena
  • addlashes (): agregue barras diagonales a la cadena s permitiendo que las comillas y las marcas de voz se usen de manera segura
  • strlen () - Obtiene el número de caracteres en una cadena
  • preg_match () - La coincidencia preg es para coincidir con el formato de una cadena
  • mail (): envía el correo desde el servidor a la dirección de correo electrónico especificada
  • md5 () - Esto calcula el hash md5 de una cadena


5. ¿Olvidó su contraseña?

La siguiente es nuestra página de contraseña olvidada. Si el usuario olvida su contraseña, podemos enviarla por correo electrónico ahora que sabemos que proporcionaron una dirección de correo electrónico real debido a la activación. Así que sin más preámbulos, aquí está el código comentado para forgot.php -

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 You need to fill in your <strong>E-mail</strong> address!"; }else{ //else continue checking 
4
 
5
 //set the format to check the email against $checkemail = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i"; 
6
 
7
 //check if the email doesnt match the required format if(!preg_match($checkemail, $email)){ //if not then display error message echo "<center><strong>E-mail</strong> is not valid, must be name@server.tld!</center>"; }else{ //otherwise continue checking 
8
 
9
 //select all rows from the database where the emails match $res = mysql_query("SELECT * FROM `users` WHERE `email` = '".$email."'"); $num = mysql_num_rows($res); 
10
 
11
 //check if the number of row matched is equal to 0 if($num == 0){ //if it is display error message echo "<center>The <strong>E-mail</strong> you supplied does not exist in our database!</center>"; }else{ //otherwise complete forgot pass function 
12
 
13
 //split the row into an associative array $row = mysql_fetch_assoc($res); 
14
 
15
 //send email containing their password to their email address mail($email, 'Forgotten Password', "Here is your password: ".$row['password']."\n\nPlease try not too lose it again!", 'From: noreply@yourwebsitehere.co.uk'); 
16
 
17
 //display success message echo "<center>An email has been sent too your email address containing your password!</center>"; } } } } 
18
 
19
 ?> <div id="border"> <form action="forgot.php" method="post"> <table border="0" cellpadding="2" cellspacing="0"> <tbody><tr> <td>Email: </td> <td><input name="email" type="text"></td> </tr> 
20
<tr> <td colspan="2" align="center"><input name="submit" value="Send" type="submit"></td> </tr> <tr> <td colspan="2" align="center"><a href="register.php">Register</a> | <a 
21
href="login.php">Login</a></td> </tr> </tbody></table> </form> </div>

Esta página no contiene nada nuevo, por lo tanto, pasaré menos tiempo revisándola. Una cosa que sí quiero mencionar es que si no lo ha notado porque hemos incluido nuestro archivo css en cada página, el diseño que utilizamos para cada página es muy similar al mantener un diseño elegante en todo el sitio web.

La página siguiente y final que haremos en este tutorial será ligeramente diferente. Esta página tiene la verificación para ver si el usuario ha iniciado sesión o no, y en este caso muestra a todos los usuarios en línea en ese momento actual (o para ser precisos en los últimos 50 segundos).



6. La página de usuarios en línea

Bien, hemos llegado a la sección del sitio web en el que necesitas iniciar sesión para ver. Como mencioné antes, este va a ser un poco diferente a los demás debido al hecho de que necesitamos verificar si el usuario ha iniciado sesión o no. Si no están conectados e intentamos ver la página, tenemos algunas opciones que podemos hacer. La primera es que podemos mostrar un mensaje de error que dice algo como "¡Debe haber iniciado sesión para ver esta página!", O podemos redirigirlos a la página de inicio de sesión. Para este tutorial creo que voy a usar el método de mensaje de error.

Así que aquí está la fuente de la página usersOnline.php -

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 You need to be logged in to user this feature!"; }else{ //otherwise continue the page 
4
 
5
 //this is out update script which should be used in each page to update the users online time $time = date('U')+50; $update = mysql_query("UPDATE `users` SET `online` = '".$time."' WHERE `id` = '".$_SESSION['uid']."'"); ?> <div id="border"> <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tbody><tr> <td><strong>Users Online:</strong></td> <td> '".date('U')."'"); 
6
 
7
 //loop for each row while($row = mysql_fetch_assoc($res)){ //echo each username found to be online with a dash to split them echo $row['username']." - "; } 
8
 
9
 ?> </td> </tr> <tr> <td colspan="2" align="center"><a href="logout.php">Logout</a></td> </tr> </tbody></table> </div>

Como mencioné, pueden ver que esta página es ligeramente diferente. No solo nos aseguramos de que estén conectados, sino que actualizamos la hora en línea manteniendo el campo en línea antes de la hora actual. Cada vez que se carga una página con ese script, se actualizará para ponerlos en línea. Ahora tenemos una página final más por hacer y luego hemos terminado. Una vez que un usuario ha iniciado sesión, debe poder cerrar sesión.



Logout.php

Esto debe considerarse como la página más fácil de hacer, y estoy seguro de que la mayoría de ustedes se alegran de escuchar. Ahora aquí está el código comentado para el archivo logout.php -

1
 <link rel="stylesheet" type="text/css" href="tut_files/style.css"> 
2
 
3
 You need to be logged in to log out!"; }else{ //if it does continue checking 
4
 
5
 //update to set this users online field to the current time mysql_query("UPDATE `users` SET `online` = '".date('U')."' WHERE `id` = '".$_SESSION['uid']."'"); 
6
 
7
 //destroy all sessions canceling the login session session_destroy(); 
8
 
9
 //display success message echo "<center>You have successfully logged out!</center>"; } 
10
 
11
 ?>

Creo que los comentarios en este archivo lo explican lo suficiente, y creo que su conocimiento de PHP ahora debería ser mucho mayor y debería poder entender la mayor parte de esto ahora.