9 usuariosA lo largo de mi vida de programador con PHP (que no ha sido muy larga) los sistemas de logueo (login) son parte de todos los sistemas que he realizado, bueno de la gran mayoría; un día teniendo problemas con las sesiones me encontre con este magnifico tutorial de como compartir sesiones entre servidores y pues decidí que debía estar en el blog.
Aclaración:
El tutorial/guía/articulo y el script fueron escritos y diseñados por Garland Foster tal y como lo indica malditainternet.com en la entrada original del artículo del cual se hará una copia fiel
Muchos sitios necesitan correr desde varios servidores, por ejemplo para aprovechar la localidad de los usuarios con respecto al servidor, para balancear la carga, para compartir usuarios registrados o simplemente como resguardopor si alguno de los sitios falla. Uno de los aspectos a contemplar para este menester es el manejo de sesiones, aqui explicamos como mantener sesiones entre multiples servidores.
Descripcion del problema
Supongamos que tenemos 2 servidores que corren el mismo sitio por ejemplo mexico.foo.org y espana.foo.org, los sitios pueden ser exactamente iguales o bien tener algunas diferencias entre si, lo que es claro es que los usuarios de foo.org pueden comenzar por cualquiera de los sitios y moverse de un sitio a otro si les parece conveniente
Sesiones
El uso de sesiones permite mantener presistencia entre las distintas paginas de un site en forma limpia y eficiente, PHP4 permite manejar sesiones en forma sumamente sencilla, por ejemplo:
Todas las paginas que usen sesiones deben empezar con session_start() o al menos hacer el session_start() antes de generar cualquier tipo de salida al browser. Una vez inicializada la sesion se utiliza session_register para guardar una variable en la sesion, notar que a session_register se le pasa el nombre de la variable y no la variable misma.
Una vez registrada la variable podemos tener otra pagina php distinta con:
Y la variable $data tomara el valor "hola" ya que habia sido guardada en la sesion con dicho nombre, se puede tambien
eliminar variables de la sesion y algunas otras cosas mas, pueden encontrar el manual en español sobre el uso de sesiones en esta direccion
Bien, podemos suponer ahora que sabemos usar sesiones, las sesiones son muy utiles para llevar datos pertenecientes al usuario, como por ejemplo su userid u otros datos importantes, si tenemos dos servidores para el mismo sitio es logico que la sesion se mantenga cuando el usuario pasa de un sitio a otro, pero esto no ocurre automaticamente.
El problema
Internamente y sin modificaciones PHP4 guarda los datos de las sesiones en /tmp, periodicamente el mecanismo de "garbage collection" elimina las sesiones vencidas, la duracion maxima de una sesion sin actividad puede configurarse en php.ini (usualmente en /usr/local/lib). Como es evidente al cambiar de un servidor a otro el segundo no tiene acceso al directorio /tmp del primero por lo que la sesion se pierde, el session_start del nuevo servidor mas que abrir la sesion anterior debe crear una nueva y perdemos los datos que veniamos arrastrando en la sesion
Una primera alternativa que funciona es usar NFS para que los dos servidores puedan acceder a /tmp en un mismo lugar, sin embargo, esto no siempre es posible y muchas veces no queremos usar NFS unicamente por esta razon.
La solucion al problema
La solucion mas practica al problema de la persistencia de la sesion entre multiples servidores reside en usar una base de datos, por ejemplo MySQL, para almacenar los datos de la sesion. De esta forma ambos servidores pueden acceder a la misma base de datos (en un solo servidor) para consultar los datos de la sesion. Tantos servidores como deseemos pueden compartir la sesion siempre y cuando puedan acceder al mismo servidor MySQL.
Para que los datos de la sesion se guarden en MySQL es necesario modificar la forma en que PHP maneja sesiones
Cambiando los Session-Handlers
PHP4 dispone de un mecanismo que permite cambiar la forma en la cual se almacenan las sesiones por cualquier metodo que el usuario desee, para ello se usa la funcion session_set_save_handler. La funcion recibe 6 parametros que son los nombres a 6 funciones que se describen a continuacion:
estruir una sesionPor ejemplo:
En el ejemplo seteamos los nombres de las 6 funciones que seran usadas para manejar sesiones, veamos ahora que prototipo debe tener y que hace cada función.
| Funcion | Prototipo | Descripcion |
| mysql_session_open | mysql_session_open ($sess_path, $session_name); |
Esta funcion es llamada para inicializar la sesion, recibe el path en donde guardar las sesiones si se usan archivos y el bombre de la sesion, en MySQL ninguno de los parametros nos interesa |
| mysql_session_close | mysql_session_close() | Esta funcion se llama cuando la pagina termina y el handler necesita dejar cerrado el archivo o lo que sea que haya usado para mantener la sesion, no elimina la sesion solo deja todo listo para volver a abrirla con open |
| mysql_session_read | mysql_session_read($key) | Esta funcion se usa para leer los datos asociados a una sesion,las sesiones se identifican por una clave que se recibe como parametro, no es necesario preouparse por los datos que se recuperan ya que esto lo maneja php4 internamente, si el usuario registra 4 variables los handlers solo guardan y recuperan un par clave-valor, la forma en que las 4 variables se serializan y desserializan esta a cargo del PHP |
| mysql_session_write | mysql_session_write($key,$val) | Esta funcion se usa para almacenar el contenido de la sesion indicada por $key, $val tiene todas las variables de la sesion serializadas y listas para ser almacenadas.Est funcion se suele llamar al final de cada script antes de hacer el close. |
| mysql_session_destroy | mysql_session_destroy($key) | Es invocada para eliminar los datos de una sesion. |
| mysql_session_gc | mysql_session_gc($maxlifetime) | Esta funcion debe eliminar todas las sesiones que tengan mas de $maxlifetime segundos de vida. |
Preparando la base para guardar sesiones
Una vez que hemos analizado como funcionan los handlers es bueno analizar como vamos a guaradar la informacion en MySQL, si entendimos bien el mecanismo solo necesitamos guardar algo de tipo clave-valor por cada sesion y ademas un timestamp que permita saber hace cuanto tiempo que no se usa la sesion. Podemos crear una tabla de la forma:
SessionID es la clave de la sesion, LastActive la ultima fecha de uso de la sesion y Data los datos de la sesion, notemos que al estar definida como PRIMARY KEY la columna SessionID esta indexada lo cual agiliza mucho el manejo de sesiones cuando hay miles de usuarios en el sistema.
Handlers para Mysql
Analicemos ahora que debe hacer cada funcion para almacenar las sesiones en Mysql
| Funcion | Descripcion |
| mysql_session_open($path,$name); | En esta funcion tenemos que abrir la conexion a la base, usar mysql_pconnect con una conexion persistente es muy recomendable, ademas seleccionamos la base con mysql_select_db. Los dos parametros que recibe la funcion se ignoran. |
| mysql_session_close(); | Aqui no hace falta hacer nada ya que no es necesario cerrar la conexion a la base |
| mysql_session_read($key); | Esto es simplemente un select a la base y devolvemos la columna data para la clave recibida. Ademas actualizar el timestamp del registro. |
| mysql_session_write($key,$data); | Aquie hay que hacer un update si la sesion ya existe o bien un insert en caso contrario. Ademas actualizamos el timestamp del registro. |
| mysql_session_destroy($key); | Un simple delete de la base |
| mysql_session_gc($maxlifetime); | Borramos de la tabla todos los registros para los cuales la diferencia entre el ultimo tiempo de acceso y el actual sea mayor al parametro recibido |
El codigo
Una vez analizado que es lo que hay que hacer solo resta programarlo, a continuacion presentamos el codigo:
Como usar el los nuevos handlers
Para usar los nuevos handlers tenemos que, en primer lugar crear la tabla PHPSessions con el codigo provisto para alguna base mysql, si se quiere se puede crear una nueva base para las sesiones, una vez creada la tabla modificar el script con los handlers indicando HOST,USER,PASS y BASE en la funcion mysql_session_open, luego solamente resta poner el script en el servidor y hacer un include del mismo "antes" del session_start, y eso es todo, pueden probarlo y ver como los datos se almacenan en la tabla y se mantiene la persistencia de la sesion. Para usarlo en otro server el proceso es el mismo, no olviden poner correctamente el HOST, USER,PASS en la funcion de conexion para que los dos servidores se conecten a la misma base MySQL.
Conclusiones
Las tecnica que hemos descripto permite compartir sesiones facilmente entre servidores y ademas ha demostrado ser mucho mas limpia y eficiente incluso en instalaciones con un unico servidor, esta es una de las cosas a tener en cuenta cuando nos lancemos a construir multiples sitios o sitios que quieran compartir usuarios en forma limpia y efectiva.
Espero que les sea tan útil como me lo fue a mi :happy_tb:
RSS feed for comments on this post. TrackBack URL
sin lugar a dudas un buen tutorial pero me surge una pregunta al momento de utilizarlo ya que yo utilizo una base de datos sq server quisiera saber que funciones utilizar sin mas que decirle y agredecer por sus respuestas gracias desde Peru.