PHP

Generación de tokens de seguridad con PHP y validación en BD MySql

A veces en algunos sistemas es necesario generar un token de seguridad y proporcionárselo al usuario como mecanismo de seguridad.

¿Que es un Token de seguridad?

Podríamos decir que un token es un mecanismo de seguridad para realizar validaciones de distinto tipo. Seguramente has escuchando o sabrás que un token es un dispositivo electrónico físico y lo utilizan muchos bancos como medio de seguridad; este dispositivo arroja de manera periódica distintas combinaciones numéricas de un solo uso, por supuesto que cada “Token” es independiente de otros y genera sus propias combinaciones numéricas.

En sistemas computacionales un token viene siendo una palabra clave alfanumérica o compuesta de solo números. Sin embargo, en ambos casos el token tiene la función de identificar al usuario que lo porta. En este articulo abordaremos la generación de token de manera computacional y en especifico con el lenguaje PHP.

Flujos donde se utilizan los token

Un token podría utilizarse en muchos flujos donde se requiera realizar una validación de autenticación. Por ejemplo, en un flujo de registro de usuarios o en un flujo de cambio de password, son dos ejemplos clásicos; en el segundo caso dicho flujo podría ser el siguiente:

  1. El flujo comienza cuando el usuario da click en algún enlace o botón para cambiar su password.
  2. Al usuario se le muestra un formulario donde se le solicita escriba su nombre de usuario, por ejemplo; su correo electrónico. Una vez que el usuario lo introduce y da click en el botón enviar se genera un token de seguridad y se inserta en una tabla temporal junto con su correo electrónico. El sistema deberá validar que el nuevo token no se repita en la tabla
  3. El sistema le envía un correo electrónico al usuario con su token.
  4. El sistema pinta un nuevo formulario con un campo para introducción del token y le informa al usuario que deberá abrir su bandeja misma donde revisar el token enviado y volver para introducir su token
  5. El usuario abre su bandeja y copia el token, regresa e introduce el token en el campo destinado para ello
  6. El sistema valida que el token exista en la tabla temporal y si existe muestra un formulario para que el usuario actualice su nuevo password. En este paso el sistema podría establecer un tiempo de expiración del token, por ejemplo 10 o 12 horas. Si en ese tiempo el usuario no vuelve y verifica su token entonces la operación de cambiar password se cancela, borrándose el token de la tabla temporal.
  7. Una vez que el usuario ha indicado su anterior password y su nuevo password (con confirmación) y da click en el botón enviar el sistema actualiza el password y borra el token de la tabla temporal.

En este ejemplo solo mostrare como generar el token y almacenarlo en la tabla temporal. Seguramente mas adelante en algún otro tutorial utilizare este ejemplo y podrá observarse mas clara la utilidad de este mecanismo de generación de tokens de seguridad.

Algoritmo de generacion del token de seguridad

Para la emulación del token de seguridad sera necesario comprender el concepto de función hash. Si revisamos la Wikipedia nos dira que las funciones hash también son conocidas como funciones picadillo, funciones resumen o funciones de digest. Estas funciones devuelven una cadena de longitud fija conocidas como valor hash.
Básicamente este valor hash es obtenido en base a una función G que recibe como entrada una cadena X (un conjunto de elementos) y efectúa una compactación (o resumen) cifrandola de manera irreversible. Entonces se podría decir que la generación de un valor hash es el resultado de una aplicación criptografica:
G(X) = valor hash

En PHP la función G podría ser Md5, SHA512 o cualquier otra función hash que sea segura. A continuación un ejemplo del uso de estas funciones en este lenguaje de programación:

Si observas, la cadena cifrada en md5 devuelve un resumen de 32 caracteres, mientras que cifrada en sha512 devuelve un un resumen de 128 caracteres. Obviamente el valor hash devuelto por la función sha512 es mas segura por la longitud de la cadena.

Volviendo al análisis de G(X) = valor hash, es importante mencionar que la cadena X cada vez que se pase a la función md5 o SH512 debería ser diferente para generar un valor hash diferente. Esta cadena podría ser por ejemplo el correo electrónico del usuario + un valor variable. El valor variable podría ser la fecha y hora actual del sistema o podría ser el tiempo POSIX (timestamp) del sistema. Entonces:
X = email+fecha actual ó
X = email+tiempo POSIX (timestamp)

En PHP existen la función date para obtener la fecha actual y la función Time() para obtener el timestamp. A continuación un ejemplo del uso de estas funciones:

Este ejemplo es muy básico y no contamos con un correo electrónico o algo parecido por lo que ese valor lo reemplazaremos por una letra o un numero elegido aleatoriamente. Ademas he pensado que un token de 32 caracteres o mas aun uno de 128 seria muy difícil para el usuario recordarlo y escribirlo uno a uno. Por ello la longitud de los tokens generados podrá enviarse a la función que genera el token de seguridad. Creo que un token de 6 u 8 caracteres es mas facil de recordar para un usuario normal. Para la generación del token e definido los siguientes requerimientos:

  • La longitud del token sera de 8 caracteres
  • Los caracteres podrán ser números ó letras únicamente, en mayúsculas
  • Un token es valido cuando no esta repetido (en una tabla temporal)

Script SQL de base de datos

A continuación copio y pego el script Sql para crear la base de datos y la tabla de MySql que se utilizara en el ejemplo:

script_sql.sql

Como se observa, la tabla esta muy sencilla y solamente consta de 3 campos e incluso de los cuales solo usaremos el campo tx_token. Agregue el campo tx_correo para que posteriormente en otros tutoriales recordemos que se usa para generar el valor hash.

El código fuente para generación de tokens de seguridad

test_token.php

Este archivo es el que realiza la generación de tokens se seguridad.

Como se observa, se han escrito 3 funciones las cuales implementan la generación del token de seguridad y realizan lo siguiente:

Funciones para generar token de seguridad
obtenCaracterAleatorio($arreglo) Aleatoriamente obtiene y devuelve un carácter del arreglo que recibe como parámetro
obtenCaracterMd5($car) Recibe un carácter y realiza el cifrado junto con el tiempo POSIX, en Md5; del valor hash obtenido toma un carácter aleatoriamente y lo devuelve
obtenToken($longitud) Recibe un numero que indica la cantidad de caracteres que debe tener un token generado. Básicamente la función define 2 arreglos; uno de letras y otro de números, los revuelve y los une. A continuación hace un ciclo para obtener el token con la cantidad de caracteres indicados en su parámetro. Para obtener cada uno de los caracteres se auxilia de las funciones obtenCaracterAleatorio y obtenCaracterMd5

El algoritmo propuesto para la generación de tokens de seguridad básicamente realiza los siguientes pasos:

  1. Se define una cadena con las letras del alfabeto A-Z y se convierte a un arreglo (linea 23 y 24)
  2. Se crea un arreglo con los números del 0-9 (linea 26)
  3. Se revuelven (o ‘barajean’) los arreglos de los pasos anteriores (linea 28 y 29)
  4. Se realiza la unión (en ingles merge) de los dos arreglos, obteniéndose un arreglo total
  5. Se crea un un ciclo for donde (linea 34)
    1. Con ayuda de la función obtenCaracterAleatorio, aleatoriamente se obtiene un elemento del arreglo total (linea 35)
    2. Con ayuda de la funcion obtenCaracterMd5 (linea 36), el elemento (un carácter) obtenido se cifra junto con el tiempo POSIX; del cual se obtiene un valor hash (linea 15) . Nuevamente con ayuda de la función obtenCaracterAleatorio se obtiene un carácter aleatoriamente del valor hash (linea 17), éste carácter es devuelto por esta función y corresponde a un carácter del token final

    Se observa claramente que la condición de paro del ciclo for es que el token final no exceda la cantidad de caracteres especificados en el parámetro de la función (linea 21), para este ejemplo 8 caracteres.

  6. Una vez obtenido el token de 8 caracteres de la linea 41 a 63 se valida que éste no exista en una tabla temporal de tokens. Si un token obtenido ya existe se realiza otra validación, en total se intenta generar un token valido 5 veces
  7. Por ultimo de la linea 65 a 71 se valida que exista un token valido y se inserta en la tabla temporal de tokens

bd_token.php

En la linea 42 se inserta este archivo el cual se encarga de conectarse con la BD MySql y deja listo un enlace de conexión, a continuación el código fuente de este archivo:

A mi consideración creo que el código esta bastante documentado por lo que me reservo la explicación.

A continuación algunas pantallas en Firefox con tokens generados, se recargo la pagina 3 veces:
Sintaxis de objeto JSON
Sintaxis de objeto JSON
Sintaxis de objeto JSON

Como dije al inicio, es un ejemplo muy sencillo y quizás algunos no le encuentren utilidad o aplicación pero verán como se utiliza en algunos tutoriales que escribiré posteriormente. Si deseas lo deseas puedes probar el ejemplo, recuerda pulsar la tecla [F5] para generar un nuevo token. Por otra parte, si deseas obtener el codigo fuente del ejemplo, desde GitHub te los puedes descargar:
Descargar ejemplo

Hasta aquí termina este articulo, espero les haya gustado pero sobre todo ojala sea de utilidad a alguien. Si tienes dudas no dudes en dejarme un comentario y en cuanto me sea posible lo contestare.

Me despido, no sin antes recordarte que regalándome un like me motivas a escribir mas.
Un abrazo, hasta pronto.

6 Comments

  1. Douglas

    Muy buen aporte amigo pero tienes algun ejemplo de como enviar el token al correo para validar al usuario y fecha estipulada vensa

  2. Douglas Uriel

    Hola amigo me podrias ayudar con un codigo saludos

  3. Muy buena este articulo de tokens de seguridad, seguí escribiendo.. saludos Agustín.

  4. La tabla temporal no le vi lo temporal en ningún lado.

  5. jose

    muy bueno pero la parte de enviar el correo al cliente ????

  6. Armando CassaU

    al fin descubrí como puedo usar el generador, básicamente la pagina a la que se redirige al usuario en la web el token , el usuario lo debe guardar en su portapapeles y enviar a través de formulario conjunto a la demás información requerida, esto me sirve para que si hay alguna reclamación el cliente pueda enviar el código generado y asi se pueda ubicar un pedido.

    ya que no soy programador, podrías facilitarme el generador en Codigo Scrip java? y el nombre del programa con el cual debo abrir los archivos?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *