Programando o Intentándolo

Autentificación de usuarios con PHP y MySQL

En este post vamos a ver como crear un sistema de usuarios usando PHP y MySQL además vamos a ver como realizar la validación del formulario con javaScript para que el usuario pueda ir viendo si va rellenando algún campo del formulario de forma incorrecta y que no tenga que esperar a enviar el formulario para ver que ha introducido algún dato de forma incorrecta.

Además de hacer una primera validación en javaScript también la vamos a hacer en PHP porque siempre debemos validar los datos en el servidor porque el usuario puede tener desactivado javaScript en su navegador o simplemente puede modificar el código en su navegador para saltarse las validaciones de forma muy simple, por lo que la validación con javaScript esta bien como una pre validación pero siempre tiene que estar acompañada de una validación en el lado del servidor que es la que realmente aporta seguridad.

Comencemos…

Formulario de registro

Vamos a empezar por donde dicta la lógica que no es otro lugar que por crear el formulario de registro. Y para poder entender mejor el código en primer lugar vamos a ver que es lo queremos, después veremos el código necesario para hacerlo y finalmente las explicaciones necesarias.

Como en cualquier formulario de registro la función principal es permitir a los usuarios registrarse introduciendo sus datos, para que el formulario sea lo más agradable para el usuario vamos a comprobar con javaScript si lo que el usuario introduce es valido (el nombre no tiene números, la edad es un numero, formato de email valido, etc.) y se lo indicamos resaltando el campo en cuestión con color verde si es correcto o rojo si no lo es.

Con esta primera validación le mostramos al usuario si ha rellenado el formulario de forma correcta o no, pero en cualquier caso le permitimos que pueda pulsar en el botón de registrase y aunque se podría desactivar este botón si hay algún campo erróneo en este caso no lo vamos a hacer para que se vea más claro que esta validación tiene como fin simplemente mejorar la interacción con el usuario.

En el caso de que el usuario intente registrarse sin rellenar el formulario de forma correcta o elija un nombre de usuario que ya este en uso le devolvemos de nuevo al formulario de registro para que introduzca los datos correctamente y para facilitarle la tarea le mantenemos los datos que ya había introducido para no hacerle volver a repetirlos.

En primer lugar cargamos los archivos PHP que tienen las clases y funciones que necesitaremos e inicializamos las variables que van a contener los valores del formulario para los casos en los que el usuario ha rellenado el formulario con algún campo de forma incorrecta evitando que tenga que volver a introducir todo de nuevo.

Después hacemos la comprobación de si se ha hecho click en el botón registrar, en caso afirmativo $_POST[‘registrar’] existirá (aunque no tenga ningún valor pues esta es la variable del botón) y entonces se creara un usuario con los datos introducidos y se comprobara si los datos son validos y si se guarda correctamente en la base de datos. Si esto sucede se envia al usuario a la pagina de login para que pueda entrar y en el caso de que algo falle se le vuelve a mostrar al usuario el formulario de registro pero con los datos introducidos previamente ya rellenados. Si es la primera vez que se entra en el formulario de registro $_POST[‘registrar’] no existirá por lo que simplemente se mostrara el formulario vacío.

En cuanto al formulario propiamente dicho como hemos dicho el valor de los input lo vamos a rellenar con las variables PHP que estarán vacías o no dependiendo de lo que haya hecho el usuario previamente.

Y la validación con javascript la vamos a hacer en el evento onblur, es decir, cuando se retira el foco del input (cuando se hace click en otro sitio, se pulsa tab, etc.) aunque perfectamente se podría ante otro evento si así se quiere.

Funciones JavaScript para validar los formularios

Estas funciones validaran el formato de cada campo mediante expresiones regulares y modificaran el estilo del formulario cambiando el color del borde del input dependiendo de si el formato es correcto o no.

Formulario de registro

Todas las funciones tienen la misma estructura que es muy sencilla, primero se define la expresión regular para comprobar el formato, después se sustituye el carácter + por su representación porque al probar el funcionamiento del formulario he visto que si introducía un + las funciones JavaScript dejaban de funcionar, con lo que así solucionamos ese problema aunque quizás no sea la mejor manera de hacerlo. Finalmente todas las funciones llaman a la función mostrarValidacion() que se encarga de aplicar un estilo CSS u otro al input en función de si la validación fue satisfactoria o no con la ayuda de jQuery

Al llamar a la función mostrarValidacion le pasamos como primer parámetro el identificador del elemento del que queremos modificar su estilo y como segundo parámetro le pasamos el resultado de realizar la validación con las expresiones regulares y el resto de comprobaciones que se hagan de forma directa.

Vamos a explicar brevemente cual es la estructura de una expresión regular mediante el ejemplo de la usada para validar el email que es la más compleja. La expresión es esta /^[a-zA-Z]+([\.]?[a-zA-Z0-9_-]+)*@[a-z0-9]+([\.-]+[a-z0-9]+)*\.[a-z]{2,4}$/:

  • Las expresiones regulares van delimitadas por /.
  • [a-z] Quiere decir que puede haber cualquier símbolo que se encuentre en el rango indicado ([a-z] letras minúsculas, [A-Z] letras mayúsculas, [0-9] números, [a-g] letras entre la a y la g, etc.])
  • Se pueden combinar los caracteres que se quiera poniéndolos seguidos dentro de los corchetes y del mismo modo se pueden añadir caracteres individuales (ejemplo: [a-zA-Z- ] puede contener letras minúsculas, mayúsculas el guion o espacios en blanco).
  • El símbolo + se usa para indicar que tiene que aparecer al menos una vez uno de los caracteres indicados previamente ([a-zA-Z]+[a-zA-Z0-9] La cadena tiene que empezar por una letra y luego puede tener tanto letras como números).
  • El símbolo ? quiere decir que el carácter o caracteres anteriores puede aparecer o no hacerlo.
  • El símbolo * indica que el carácter siguiente tiene que aparecer obligatoriamente (un email tiene que tener el símbolo @).
  • El símbolo ^ indica que la cadena debe comenzar con el carácter o caracteres que le sigue.
  • El símbolo $ indica que la cadena debe finalizar con el carácter o caracteres que le preceden.
  • {2,4} indica la longitud del grupo de caracteres que le precede (en este caso el 2 seria el tamaño mínimo y el 4 el máximo).

Visto esto podemos leer la expresión regular anterior de la siguiente forma. Un email tiene que empezar por una letra y puede contener puntos antes de @ siempre que tengan alguna letra, número o guion (ej. abC.Y-op) después obligatoriamente tiene que tener la @ y detrás puede tener una cadena de numero y/o letras con puntos y guiones en su interior (ej. gm4il) finalmente un email valido tiene que terminar con un punto (obligatorio) y una cadena de caracteres de entre 2 y 4 letras.

El código JavaScript de estas funciones de validación es el siguiente:

Formulario de login

Una vez que ya tenemos “todo” lo necesario para registrarnos vamos a ver la parte necesaria para poder logearnos.

Formulario de login

El código SQL para generar la tabla anterior es:

En primer lugar crearemos el formulario de login que contendrá los dos campos de toda la vida, usuario y contraseña.

Lo primero que hacemos en el formulario de login es comprobar si el usuario ya esta logeado y en ese caso le redirigimos directamente a la página que nosotros queramos, y si no esta logeado entonces le mostramos un formulario para que pueda introducir sus datos que validaremos en el archivo login.php que veremos a continuación. Si los datos introducidos por el usuario no coinciden con ningún usuario registrado desde login.php volveremos a ser redirigidos al formulario de login con el parámetro error en la url (formulario_login.php?error=error) y entonces se mostrara en el formulario que los datos que hemos introducido no son correctos y de este modo poder ver que esta ocurriendo y porque seguimos en la página de login.

Antes de meternos en otras cosas vamos a ver como sería el archivo login.php para no perdernos e ir entendiendo lo que estamos haciendo.

Lo que hacemos es simplemente comprobar si los datos del usuario son correctos y dependiendo del resultado de esta comprobación creamos una sesión y le añadimos los datos del usuario, en este ejemplo se añade el usuario y la password a la sesión para ver que se pueden añadir varios atributos, pero la password no sería necesario añadirla y lo mejor sería no hacerlo. Si los datos no son validos volvemos a la pagina del formulario de login como decíamos antes.

Lógica del sistema de usuarios

Hasta el momento simplemente hemos visto las páginas de registro y login y las funciones javaScript para hacer la validación del formulario.

Ahora vamos a ver que es lo que hay por detrás de estos formularios que es lo que nos permite tener un sistema de autentificación para poder tener un control sobre los usuarios que pueden acceder o no a nuestras páginas.

Base de datos

Vamos a usar una base de datos MySql ya que es gratuita y muy raro será el sitio en el que no dispongamos de MySQL y además es muy sencillo de instalar en un entorno local. Para este ejemplo simplemente necesitamos una tabla para almacenar los usuarios como la siguiente:

Tabla usuarios de la base de datos

Para poder cambiar la base de datos de forma rápida vamos a usar el archivo config.php donde vamos a establecer los datos de acceso a la base de datos y de esta forma para cambiar de base de datos solo tendremos que modificar los valores de este archivo siempre y cuando mantengamos la estructura de la base de datos.

Modelo de datos

Para algo tan simple como un sistema de usuarios el modelo de datos se reduce a un par de clases usuarios, roles, etc. en este caso nos vamos a quedar en lo más sencillo por lo que simplemente tendremos una clase para los usuarios.

Sistema de validación

El nucleó de un sistema de validación son las funciones que permiten registrar los usuarios y validar que las credenciales introducidas son correctas, además de estas dos funciones esenciales tenemos otras dos funciones para validar que los datos del formulario de registro son correctos y que el nombre de usuario elegido no esta siendo usado ya.

Estas funciones son bastante sencillas por lo que no debería haber mayor problema para entender como funcionan pero por si acaso vamos a ver los detalles que merece la pena comentar para que quede claro que es lo que estamos haciendo.

La función validarUsuario($usuario) simplemente hace uso de las funciones de la clase validadorFormularios que veremos posteriormente para tener en un único lugar todas las validaciones juntas y que se puedan hacer todas las validaciones llamando a una sola función. (Esta función se usa en formulario_registro.php)

En la función insertarUsuario($usuario) se hace así de sprintf() para generar cadenas con formato y de este modo nos aseguramos de que en cada campo estamos metiendo el tipo de dato que realmente necesitamos (%d => numero, %s => cadena texto) y también se usa la función real_escape_string que escapa caracteres especiales en la cadena dada para evitar problemas aunque al validar los campos el único que supuesta mente podría darlos es la contraseña por que el resto tienen controlados los caracteres que se pueden insertar, pero mejor pasarse que quedarse cortos. Finalmente vamos a ver la forma en la que se encripta la contraseña:

  1. Contatenamos la contraseña y nombre de los usuarios para que la cadena ha desencriptar ea más larga y más compleja.
  2. Ciframos la contraseña mediante sha1.
  3. Volvemos a cifrarlo usando md5, para hacerlo un poco más dificil.

La función para comprobar si existe un usuario no tiene nada de especial porque solo

Y finalmente referente a la función comprobarUsuario($id,$pass) recordar que las contraseñas nunca se desencriptan, sino que cuando se quiere comprobar si una contraseña es correcta lo que se hace es volver a cifrarla y comparar que el resultado cifrado es el mismo.

Por ultimo vamos a ver las funciones de validación en PHP que son prácticamente iguales que las vistas para javascript y de hecho dentro de estas funciones se ejecutan esas funciones javaScript para que la se muestre la parte visual de estas validaciones.

Ya tenemos todo lo necesario para poder registrar usuarios y para permitir que se autentifiquen pero nos falta lo más importante que no es otra cosa que restringir el acceso a las páginas que queramos que solo puedan acceder los usuarios autentificados y es tan sencillo como comprobar que existe la variable id en $_SESSION cosa que solo sucede cuando el usuario esta previamente logeado, se guarda en login.php cuando los datos introducidos en el formulario de login son correctos.

La siguiente página nos sirve como ejemplo de que el usuario esta logeado y recuperamos los datos del usuario que habíamos guardado en la sesión (el usuario y la contraseña) y si no esta logeado le redirigimos al formulario de login.

Aunque esta forma de actuar esta bien es más sencillo invertir el if y de este modo no tenemos que incluir el contenido de la pagina dentro del if.

Para terminar como siempre puedes descargarte el código completo de este ejemplo desde este enlace.