Manejando usuarios con PHP Sessions y MySQL – Parte I

Cada tanto tiempo a uno se le pide que creemos un nuevo sitio , un nuevo sistema o hasta una pequeña aplicación distribuída basada en PHP, y siempre que pasa uno de los primeros pensamientos va orientado al manejo de sesiones de los usuarios, o sea, poder ingresar de forma segura con un nombre y una contraseña.

Aunque esto no implica mucha dificultad, el problema por lo general es que lo programamos una ves y nos olvidamos, por lo tanto para refrescar aquí estoy yo.

Sin más, manos a la obra.

Recientemente, he tenido la ocasión de trabajar en un proyecto con un pequeño grupo de personas; y una parte importante era un dashboard o tablón de herramientas generales que sólo podía ser accedido por usuarios registrados en el sitio.

Muchas de estas herramientas necesitaban estar bajo el ámbito del usuario que se encontraba en ese momento, por lo que el sistema debía saber en todo momento quien era y si tenía permitido ver esto o aquello.

En esta entrada veremos un pequeño sistema que incluye la registración, el formulario de acceso, la sesión, manejo y permanencia de la misma y por supuesto la destrucción de la misma. Todo en PHP.

De antemano, doy por que saben cómo crear una base de datos con una simple tabla de usuarios y sesiones.

 

Parte 1: el proceso de registro

 

El formulario de registro

 

Un lugar natural para comenzar a construir un sitio que requerirá a usuarios registrarse para poder ingresar, es el formulario de registración en sí mismo. Como uno puede esperar, un simple formulario web bastará y se verá más o menos así:

formulario de registro

Y tiene un código simple como este:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Nuevo Registro</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>
<h3>Formulario de Registro</h3>
<p><font color="orangered" size="+1"><tt><b>*</b></tt></font> indica campo obligatorio</p>
<form method="post" action="<?=$_SERVER['PHP_SELF']?>">
<table border="0" cellpadding="0" cellspacing="5">
<tr>
<td align="right">
<p>ID de usuario</p>
</td>
<td>
<input name="newid" type="text" maxlength="100" size="25" />
<font color="orangered" size="+1"><tt><b>*</b></tt></font>
</td>
</tr>
<tr>
<td align="right">
<p>Nombre completo</p>
</td>
<td>
<input name="newname" type="text" maxlength="100" size="25" />
<font color="orangered" size="+1"><tt><b>*</b></tt></font>
</td>
</tr>
<tr>
<td align="right">
<p>E-Mail</p>
</td>
<td>
<input name="newemail" type="text" maxlength="100" size="25" />
<font color="orangered" size="+1"><tt><b>*</b></tt></font>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<hr noshade="noshade" />
<input type="reset" value="Reset Form" />
<input type="submit" name="submitok" value=" OK " />
</td>
</tr>
</table>
</form>
</body>

</html>
<!-- Ya existe una pequeña porción de código php incluída:

<form method="post" action="<?=$_SERVER['PHP_SELF']?>"> -->

Notemos el atributo “action“, lo que haremos es submitear el contenido del formulario a la misma página que contiene el formulario. Mediante la variable PHP $_POST[‘submitok’] nuestro código podrá manejar los registros del formulario así como mostrar el formulario en sí.

También estamos usando una forma relativamente nueva de utilizar la variable $_SERVER['PHP_SELF'] (si no están familiarizados con esto, la expresión <?=expression?> es funcionalmente idéntica a <?php echo expression; ?>, y se obtiene el mismo resultado).

Ahora que ya tenemos el formulario, podemos seguir completando el script de registro.

El Script de Registro

Si alguna vez hemos manejado sitios o páginas que utilicen BBDD (Bases de Datos), el script es muy sencillo y ya que estamos podemos escribir algunas funciones de conexión y desconexión que nos serán muy útiles. Para esto, y refactorizando mentalmente, voy a usar dos archivos principales, uno llamado db.php que incluirá los scripts de la BBDD; y otro llamado common.php que tendrá funciones generales.

Primero, aquí el código de db.php:

<?php // db.php
 
$dbhost = "localhost";
$dbuser = "user";
$dbpass = "password";
 
function dbConnect($db="") {
    global $dbhost, $dbuser, $dbpass;
    $dbcnx = @mysql_connect($dbhost, $dbuser, $dbpass)
        or die("La Base de Datos parece no estar respondiendo.");
 
    if ($db!="" and !@mysql_select_db($db))
        die("No se puede acceder a la Base de Datos.");
 
    return $dbcnx;
}
?>

La función dbConnect definida puede ser llamada con o sin argumentos, porque hemos asignado un valor por defecto ("") al argumento $db en la declaración de la función. Esta se conecta a la BBDD usando los datos que ya tenemos que tener conocidos ( el server $dbhost,  el usuario $dbuser, y el password del usuario $dbpass). Asumiendo que todo se dé sin error, entonces la función devuelve una referencia a dicha conexión.

El segundo archivo, common.php, también contiene sólo una función:

<?php // common.php
 
    function error($msg) {
    ?>
        <html>
            <head>
              <script language="JavaScript">
              <!--
              alert("<?=$msg?>");
              history.back();
              //-->
              </script>
            </head>
            <body>
            </body>
        </html>
    <?
    exit;
    }
?>

 

Usaremos esta función de error para notificarles al usuario cuando han hecho algo mal. Toma un mensage de error como argumento y lo imprime a modo de pop-up de javascript, antes de volver a la página anterior. Esta función termina con un comando exit, que escapa del script cuando algo anda mal con el mismo.

Ahora, ya tenemos la parte aburrida, ahora a juntar ambos archivos con el script de registro (signup.php). Lo primero a hacer es incluir ambos archivos:

<?php // signup.php

include 'common.php';
include 'db.php';

Asumimos que dichos archivos se encuentran en el path raíz junto con signup.php. No es requerimiento peroe s una buena práctica inlcuir a  ambos archivos desde paths relativos a carpetas dentro del sitio, algo que sea un poco más distintivo o que nos sirva de framework (y que es mucho más seguro, ya que no quedan expuestos en la raíz web).

Leugo, deberemos ver que todo estuvo bien mediante la presencia de la variable  $_POST['submitok'] que indica que un formulario fue llenado y enviado, si no existe la misma, entonces el script mostrará el formulario de registro.

 

if (!isset($_POST['submitok'])):
// Mostrar el formulario de registro
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Nueva Registración</title>
...

El resto del script es responsable del procesamiento del formulario, agregando el nuevo usuario a la BBDD.

Antes de seguir, miremos mi tabla en MySQL:

mysql> CREATE TABLE user (
-> ID INT PRIMARY KEY AUTO_INCREMENT,
-> userid VARCHAR(100) UNIQUE NOT NULL,
-> password CHAR(16) NOT NULL,
-> fullname VARCHAR(100) NOT NULL,
-> email VARCHAR(100) NOT NULL,
-> notes TEXT);

Ojo! Es una tabla base, es muy posible que en un desarrollo unpoco serio necesites un par de columnas más, pero para el caso de esta explicación alcanza.

Volvamos al script, cuando la variable $submit es detectada, el sistema debe prepararse para insertar una nueva fila en la BBDD usando la función  dbConnect de db.php:

 <?php
else:
// Procesar formulario
dbConnect('sessions'); //ASUMO que la BBDD se llama sessions!!!

Luego revisamos que los campos del formulario hayan sido completados, y si alguno está vacío, entonces enviaremos un mensaje de error que será utilizado por  common.php como vimos antes.

 if ($_POST['newid']=='' or $_POST['newname']==''
or $_POST['newemail']=='') {
error('One or more required fields were left blank.\n'.
'Please fill them in and try again.');
}

Ahora, precisamos determinar que el ID seleccionado no esté en uso por otro usuario en la BBDD, si existe el nuevo registrante deberá elegir otro. O sea, está consulta devolverá un 0 o un 1, y como son valores únicos no necesitamos ningún loop ni nada semejante. En cambio usamos la función  para obtener el valor de la primer columna de la primer fila:

 // Verifico la existencia del ID
$sql = "SELECT COUNT(*) FROM user WHERE userid = '$_POST[newid]'";
$result = mysql_query($sql);
if (!$result) {
error('ha ocurrido un error '.
'submission.\n Si esto continúa por favor '.
'contactarse con you@example.com.'); //NO OLVIDAR CAMBIAR ESTE MAIL
}
if (@mysql_result($result,0,0)>0) {
error('Usuario existente.\n'.
'Por favor elija otro.');
}

 

Finalmente, haremos el insert en la BBDD:

 $sql = "INSERT INTO user SET
userid = '$_POST[newid]',
password = PASSWORD('$newpass'),
fullname = '$_POST[newname]',
email = '$_POST[newemail]',
notes = '$_POST[newnotes]'";
if (!mysql_query($sql))
error('Ha ocurrido un error'.
'.\n Si esto persiste'.
'contactarse a you@example.com.'); //MODIFICAR EL CORREO

Y ya tenemos al usuario registrado,  enviaremos entonces un correo electrónico informando el password que se le ha asignado. Esto se hace muy fácilmente utilizando la  función de PHP  email:

 // Email el password al sujeto.
$message = "Hola!
 
Su cuenta personal ha sido creada, para ingresar, por favor hacer click en le siguiente enlace:
 
http://www.example.com/
 
Su ID personal y password son:
 
userid: $_POST[newid]
password: $newpass
 
El password lo puede cambiar en cualquier momento que lo desee.
Si tiene algún problema, favor de contactarnos a  <you@example.com>.
 
-Kaos
Your Site Webmaster
";
 
mail($_POST['newemail'],"Your Password for Your Website",
$message, "From:Your Name <you@example.com>");

Modifique este mensaje a gusto y placer, poniendo todos los datos correctos y necesarios. 😉

Y por último, la sección en HTML que avisa de una registración exitosa:

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> Registración Completa </title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1" />
</head>
<body>
<p><strong>Registración Completa !</strong></p> 
<p>Su userid y password Han sido enviados por correo electrónico a <strong><?=$_POST[newemail]?></strong>, 
Para acceder, click en <a href="index.php">here</a> para volver a la página de ingreso.</p> 
</body> 
</html> 
<?php endif; ?>

 

Noten que te rdirige a la página de login como página principal, porque consideramos que todo el sitio debería ser seguro y con contenidos accesibles sólo a los usuarios registrados y con la sesión abierta.

Ya tenemos las bases de nuestras sesiones y manejo de las mismas, en la próxima entrega finalizaremos con los accesos, .password olvidado, seguridad y chukuchukuchuku.

 

Hasta la próxima!

Dejá un comentario