La mayor parte de las páginas web orientadas a servicios deben implementar un sistema de registro e identificación de usuarios. Varias veces he tenido que desarrollar o modificar el código asociado y debo admitir que, aunque simple, resulta engorroso. Al tratarse de una parte tan crítica de la aplicación, es necesario comprobar muchos detalles: duplicidad de nombres, contraseñas seguras, permitir su restauración, evitar inyección de código, etc. Para el último proyecto, he decidido poner un poco de orden. Aunque iré dando más detalles conforme lo vaya desarrollando, primeramente voy a describir algo tan preliminar como la gestión de usuarios. Construiremos una librería en JavaScript para su manejo, que creo que puede resultar útil a otros por lo común de la necesidad, y de paso sirve de excusa para introducir algunos conceptos interesantes. Para quien se encuentre algo perdido, he escrito también una breve introducción a la programación web. Dicho esto, comenzamos.
La gestión de usuarios comprende varias funciones, que se pueden clasificar en el registro, la identificación y la modificación de datos o restauración de contraseñas. Las operaciones deben repartirse entre el código del cliente y el servidor. Es en este último donde de forma efectiva se hacen las comprobaciones convenientes, se inicia y mantiene la sesión, y se trabaja contra la base de datos. Pero del lado del navegador corre parte del manejo de los datos, y es importante una buena presentación y usabilidad. Cuando el usuario accede por primera vez a la web, usualmente dispone de opciones tanto para identificarse como para darse de alta.
Vamos a seguir un orden cronológico, y por tanto comenzamos con el registro. El código de un formulario de registro podría ser como sigue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<div id="newuser" class="hidden"><form id="newuser_form" action="javascript:;" name="newuser_form">Nombre: <input id="newuser_id" name="newuser_id" type="text" /> <span id="newuser_id_message" class="error"> </span> Nombre completo: <input id="newuser_descriptor" name="newuser_descriptor" type="text" /> <span id="newuser_descriptor_message" class="error"> </span> Contraseña: <input id="newuser_password" name="newuser_password" type="password" /> <span id="newuser_password_message" class="error"> </span> Confirmar contraseña: <input id="newuser_password2" name="newuser_password2" type="password" /> <span id="newuser_password2_message" class="error"> </span> Correo: <input id="newuser_email" name="newuser_email" type="text" /> <span id="newuser_email_message" class="error"> </span> <div id="test_captcha"> <div id="captcha"><img id="img_catpcha" alt="" /></div> <input id="newuser_captcha" name="newuser_captcha" type="text" /> <input id="new_captcha" class="button" type="button" value="No se lee" /> <span id="newuser_captcha_message" class="error"> </span> </div> <input id="newuser_submit" type="submit" value="Enviar" /> </form><input id="newuser_close" type="submit" value="Cerrar" /> </div> |
Se trata de un formulario inicialmente oculto, para lo cual se ha definido la clase hidden, con el estilo asociado:
1 2 3 |
.hidden { display:none; } |
Para hacerlo visible, incluimos un botón de registro con identificador login_create y el siguiente código asociado:
1 2 3 4 5 6 |
// Create account $("#login_create").bind("click", function() { $("#login").hide(timeshow); $("#newuser").show(timeshow); $("#captcha").html("<img src="captcha.php?p="+Math.random()+"" alt="" />"); }); |
Es decir, al pulsar sobre él se llevan a cabo tres operaciones: se oculta la capa donde está el formulario de identificación (el que veíamos en la primera imagen), se muestra el de registro y por último se carga una imagen captcha, que debe generar la URL captcha.php. El uso de un parámetro aleatorio no cumple otro papel que el de forzar al navegador a realizar dicha petición si se recarga la página, en vez de mostrar la que pueda haber guardado en caché.
Hecho esto, estaremos viendo una página de registro al uso (nota: he dejado una presentación casi minimalista, en parte para no desviar la atención de los elementos esenciales):
Antes de considerar el envío del formulario, es conveniente agregarle cierta funcionalidad para hacer varias comprobaciones simples. Una de ellas suele ser la coincidencia de las dos contraseñas; basta, al salir del campo asociado, efectuar la comprobación. Para mostrar las notificaciones de error se han agregado al formulario contenedores en línea (etiquetas span). Un poco de CSS para darles color rojo y algo de jQuery para mostrarlos sirve para llamar la atención sobre el problema existente.
1 2 3 4 5 6 7 8 9 |
// Check second password $("#newuser_password2").bind("focusout", function() { password=$("#newuser_password").val(); password2=$("#newuser_password2").val(); if (password!=password2) $("#newuser_password2_message").text("Las contraseñas no coinciden.").hide().fadeIn(timefade); else $("#newuser_password2_message").text("").show(); }); |
La verificación que acabamos de lleva a cabo se realiza con facilidad en el equipo cliente. Otro asunto es comprobar, por ejemplo, el correo, donde además de asegurar que cumple con la sintaxis adecuada, es preciso asegurar que no esté ya en uso. Para lo primero, se puede usar una expresión regular. Respecto al segundo chequeo, debemos hacer una llamada al servidor. La siguiente función pregunta a la página a.php, que va a ser la encargada de la gestión de usuarios; y lo hace pasando varias variables: a (de acción), con valor «check» para indicar que queremos efectuar una comprobación; item con valor «email», para decir de qué tipo, y por último el propio correo electrónico. El servidor nos devolverá el texto «1» si el correo está efectivamente en uso y «0» si no es así.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Check email $("#newuser_email").bind("focusout", function() { email=$("#newuser_email").val(); if (email.match(/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+/)==null) $("#newuser_email_message").text("Correo electrónico no válido.").hide().fadeIn(timefade); else { $.ajax({ type: "POST", url: "a.php", data:{a:"check",item:"email",value:email} }).done(function(data) { if (data=="1") $("#newuser_email_message").text("El correo ya existe").hide().fadeIn(timefade); else $("#newuser_email_message").text("").show(); }); } }); |
También debe asegurarse un usuario válido, contraseña segura, etc. Estas comprobaciones, por otro lado, no eximen de volverlas a repetir en el lado del servidor una vez se envíe el formulario. Para efectuar dicho envío, vamos a recurrir de nuevo a la URL a.php, pasándole los campos del formulario, además de una variable a con valor «register». Como ya habréis podido adivinar, esta variable informa al código en el servidor del tipo de acción que se pretende realizar. En el caso concreto del registro, se han planteado tres respuestas: «1» si el resultado es correcto; «2» si no se ha escrito correctamente el captcha, en cuyo caso se pide otro; y «0» si el usuario se empeña en ignorar las comprobaciones que acabamos de mencionar y envía el formulario con errores.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// User creation $("#newuser_form").bind("submit", function() { $.ajax({ type: "POST", url: "a.php", data:{a:"register", user:$("#newuser_id").val(), descriptor:$("#newuser_descriptor").val(), password:$("#newuser_password").val(), email:$("#newuser_email").val(), captcha:$("#newuser_captcha").val() } }).done(function(data) { if (data=="2") { $("#newuser_captcha_message").text("Los caracteres no coinciden").show().fadeOut(timefade); $("#captcha").html("<img src="captcha.php?p="+Math.random()+"" alt="" />"); $("#newuser_captcha").val(""); } if (data=="1") { $("#newuser").hide(timeshow); $("#login").show(timeshow); alert("Se le ha enviado un correo de confirmación de cuenta. Revíselo antes de entrar."); } }); }); |
Para hacer las cosas correctamente, todo el tráfico, pero en especial el envío de la contraseña, debería hacerse bajo una conexión segura. Y si todo ha marchado correctamente, el servidor debe enviar un correo electrónico que permita confirmar la cuenta del usuario. En la próxima entrega veremos cómo se debe completar el registro.
Esta entrada continúa en Librería Users.js (2). Identificación.
Recursos asociados:
Librería User.js para gestión de usuarios
Ejemplo de uso de la librería User.js


