PHP-TUT-17 Cookies y Sesiones

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

Cuando nos conectamos a un sitio web remoto solemos hacerlo mediante el protocolo http://. Una conexión típica a Internet tiene la forma http://www.eldesvandejose.com. También podemos usar, en determinadas páginas, el protocolo https:// (las llamadas páginas seguras). Ambos son lo que se conoce como protocolos sin estado. Esto significa que ni el servidor ni el cliente conservan memoria de los pares nombre-valor empleados en una página, al pasar a otra, a menos que pasemos dichos datos específicamente, mediante un formulario. Para solventar esto aparecen las cookies y las sesiones. Ambas son, en su concepto básico, formas de almacenar provisionalmente unos datos que otra página recopilará para seguir trabajando con ellos. La diferencia fundamental es el lugar de almacenamiento de dichos datos. Las cookies se usan para guardarlos en el cliente y las sesiones para guardarlos en el servidor. Ambos sistemas tienen sus ventajas y sus limitaciones. Por ejemplo, si recurrimos a las sesiones, y nuestro sitio cuenta con muchas visitas simultáneas, el servidor se puede sobrecargar. Si preferimos usar cookies y el cliente las tiene desactivadas, se presentará un fallo (solucionable, en última instancia). Cuando necesitamos almacenar datos para pasarlos de una página a otra, el empleo de sesiones o de cookies es, en algunos casos, una cuestión de criterio personal. En otras situaciones, debido al alcance que deban tener los datos, se presenta como más adecuado un sistema u otro. En este artículo aprenderemos a usar ambas técnicas y a decidir cuál elegir en cada caso.

Como medida preliminar, olvida los mitos que hayas podido oír respecto a estas técnicas. Ni las cookies son peligrosas para el ordenador del cliente, ni las sesiones son una tecnología complicada, accesible sólo a los elegidos. Son, simplemente, modos de almacenamiento de pares nombre-valor, así como de matrices si procede, que resultan muy útiles.

COOKIES

Una cookie (“galletita”, en inglés) es un archivo de texto que contiene el nombre de una variable y su valor. Este archivo se almacena en el ordenador cliente durante la navegación por Internet y puede estar disponible para recuperar el valor de la variable en posteriores navegaciones. Recuerde esto: una cookie solo puede contener texto plano, no programas ejecutables ni nada potencialmente peligroso. Cuando el usuario se conecta a Internet y entra en nuestro sitio, el código en el servidor es el encargado de almacenar la cookie en el cliente.

Y, ¿para qué querríamos almacenar una variable en el ordenador del cliente? Puede haber tantas respuestas a esta pregunta como seas capaz de imaginar. Quizás uno de los usos más populares es el del idioma del propio usuario. Tú creas un sitio web destinado a visitantes de diversas nacionalidades. Para ello creas una página y luego haces una copia en la que cambias los textos a otro idioma. Tienes, por tanto, dos copias de la página. Por ejemplo, una en español y otra en inglés. Si un usuario se conecta por primera vez a tu sitio, tiene opción a elegir en qué idioma quiere ver los contenidos. El nombre del idioma elegido queda almacenado en una variable en el propio ordenador del cliente (una cookie). Ahora supongamos que el internauta se vuelve a conectar a tu sitio, digamos, al día siguiente. El servidor encuentra la cookie, lee el idioma que eligió el usuario y le remite, directamente, a la página en dicho idioma. Esto crea un efecto de personalización que contribuye a que la persona se sienta cómoda visitando el sitio.

Veamos cómo usar este mecanismo. En primer lugar necesitamos un script que determine si el usuario se conecta a nuestro sitio por primera vez, o si ya se ha conectado antes, es decir, si en su ordenador no existe ninguna cookie nuestra que almacene su idioma o si ya está grabada. En caso de que no exista la cookie, deberá cargarse una página donde se le pida al usuario su idioma y deberá crearse la cookie. En el caso de que ésta ya exista, deberá leerse y redireccionar al usuario a la página en su propio idioma. El mecanismo responde al esquema de la siguiente imagen:

Comprobando la cookie

Comprobando la cookie

Analiza el esquema. Verás que, en el acceso al sitio por la página principal, existe un script que verifica si el cliente que se ha conectado tiene grabada una cookie con una variable relativa al idioma del usuario. Si no se encuentra esta variable, se llega a una página donde se le pide que elija su idioma. Desde ahí, se salta a otra página donde se graba la variable y, por fin, a la página de contenidos elegida. Si existe la cookie, se lee la variable y, en función de su valor, se salta a la página elegida.

Cuando un script debe leer una variable que está grabada en una cookie se recurre a una matriz propia de PHP, llamada $_COOKIE. Se trata de una matriz asociativa cuyo índice es el nombre de la variable que esperamos poder leer desde la cookie del cliente. En el ejemplo de las páginas con varios idiomas, el idioma del cliente podría, por ejemplo, almacenarse en una variable llamada $idiomaUsuario, con lo que para leer dicha variable desde una cookie usaríamos una llamada como la siguiente: $_COOKIE["idiomaUsuario"].

Para grabar una cookie en el ordenador del cliente usamos la función setcookie(). Ésta puede recibir hasta seis argumentos, aunque sólo el primero es obligatorio, siendo los demás opcionales. Los seis parámetros que se le pueden pasar a esta función aparecen en la siguiente tabla:

ARGUMENTO DATO USO
Nombre de la variable Cadena Este parámetro es obligatorio y se usará como índice de la matriz asociativa $_COOKIE para recuperar el contenido.
Valor de la variable Cadena | numérico | booleano El valor de la variable. Si no se pone, la función elimina la cookie en el equipo del cliente.
Duración Numérico Se usa para determinar el tiempo durante el que la cookie es válida. Si se intenta leer la cookie después del plazo establecido, no se puede y hay que grabarla de nuevo. Si no se incluye este parámetro, la cookie expira al cerrar el navegador.
Dominio Cadena El dominio desde el que se leerá la cookie. Si no se incluye, se puede leer desde cualquier dominio.
Ruta de acceso Cadena La carpeta, dentro del servidor, desde la que se leerá la cookie. Si no se incluye, se puede leer desde cualquier carpeta.
Página segura Booleana Si esta variable vale true, sólo se puede leer la cookie desde una página segura (https).

Para aclarar cómo funciona todo esto vamos a ver unos listados que responden al esquema visto anteriormente. No cargues todavía ninguno de estos scripts en tu navegador. Primero analicemos su funcionamiento. Empezaremos por el que corresponde a la página principal, donde se comprueba si ya existe la cookie. En este ejercicio lo hemos llamado usoDeCookies.php, para darle el sentido propio del ejemplo. En un sitio real este código estaría incluido en index.php, que es el nombre que tiene que tener la página cero de cualquier sitio en Internet.

Observa cómo se intenta leer el valor de la variable $_COOKIE["idiomaUsuario"]. Si la cookie no existe, se fija el nombre de la página a la que saltaremos como la destinada a preguntarle al usuario su idioma. Si existe la cookie y el valor de la variable es sp, se irá a la página en español. Si no, se irá a la página en inglés. He diseñado este ejercicio de modo que sólo incluya dos posibilidades de idioma, para simplificarlo, pero podría haber más.

El listado de la página que le pregunta el idioma al usuario es muy simple. Lo he llamado pedirIdioma.htm:

Como ves, sólo se trata de dos enlaces convencionales. Ambos llaman a la misma función JavaScript, cada uno con un argumento que será el valor que represente al idioma elegido. La función sólo toma ese argumento y se lo entrega al script encargado de grabar la cookie en el equipo cliente, cuyo nombre es grabarCookie.php y cuyo listado aparece a continuación:

Observa la línea que graba la cookie. El primer parámetro establece el nombre de la variable. El segundo establece el valor que tendrá la variable. Este valor se obtiene desde la URL, tal como es invocado este script desde pedirIdioma.htm. El tercer valor es la fecha de caducidad de la cookie. Se ha tomado el momento actual (cuando se ejecuta el script) y se le han sumado 24 horas (86.400 segundos). Si el usuario vuelve a visitar el sitio antes de que hayan transcurrido las veinticuatro horas, se le redireccionará a la página en su idioma. Si vuelve a entrar pasado el plazo establecido (o desde otro ordenador), se le volverá a preguntar su idioma. Normalmente se establece un plazo pensando en la posible frecuencia de visitas. Si no se hubiese especificado el plazo de caducidad, la cookie expiraría al cerrar el navegador, con lo que no tendría mucho sentido en este ejemplo.

Y ahora sí. Cargua en tu navegador el script usoDeCookies.php. Como es la primera vez que lo cargas y tu cookie aún no existe, se te pasará a la página donde se te pregunta tu idioma.

Pulsa, por ejemplo, en el enlace correspondiente a la versión en español. Eso te llevará a la página encargada de grabar la cookie. Desde ahí saltará a la página principal y, como ya existe la cookie, irá a la página en español.

Si ahora cierras tu navegador y, a continuación, lo vuelves a abrir cargando el script usoDeCookies.php te reconducirá, directamente, a la página en el idioma elegido. Durante 24 horas será así. Pasado el plazo, volverás a ver la la selección de idioma. Si quieres eliminar la cookie antes de que se cumpla el plazo, deberás ejecutar el script borrarCookie.php, cuyo listado aparece a continuación:

Como ves, es muy simple. En la página no verás nada (queda totalmente en blanco), ya que no hay ningún contenido visualizable. Lo que hacemos es “establecer” la cookie con el parámetro obligatorio del nombre de la variable… y sin ningún otro. Esto elimina la cookie en el cliente. Si ejecutas este script y, a continuación vuelves a ejecutar usoDeCookies.php te encontrarás, de nuevo, con la página de selección de idioma.

Sin embargo, aún podemos mejorar esto. Cuando se graba una cookie, como en este caso, para que expire a las 24 horas, eso es, exactamente, lo que sucede. Si el usuario entra de nuevo en el plazo establecido, la cookie funciona, pero pasado ese plazo, la cookie expira indefectiblemente, ya que no se renueva de modo automático. Tendríamos que contar con un mecanismo que, al entrar dentro del plazo establecido, renovara la cookie por otro lapso similar. Observa el listado del siguiente script, llamado usoDeCookiesRenovables.php:

Observa que si la cookie ya existe vuelve a ser grabada de nuevo, prolongando, así, su periodo de validez.

Hasta ahora sólo hemos hablado de los tres primeros argumentos. Si establecemos el cuarto, que corresponde al nombre de dominio, la cookie sólo podrá ser leída desde el dominio que se especifique en este parámetro. Esto no es aconsejable si piensas que puedes cambiar el nombre de tu dominio en el futuro.

Si estableces un directorio en el quinto parámetro, el script que lee la cookie deberá estar en dicho directorio en el servidor, o no se podrá leer la cookie.

Por último, si estableces el sexto argumento con el valor true, la cookie sólo podrá ser leída por un script al que se acceda mediante una capa segura (protocolo https://). Esto es importante si la cookie almacena algún valor sensible, tal como un número de tarjeta de crédito o similar (en una tienda virtual, por ejemplo). Grabar datos potencialmente delicados en cookies es muy desaconsejable.

También podemos grabar cookies que contengan una matriz. Por ejemplo, supongamos el siguiente fragmento de código:

$matriz["primeraClave"] = "Primer elemento";
$matriz["segundaClave"] = "Segundo elemento";
$matriz["terceraClave"] = "Tercer elemento";
setcookie ("matriz", $matriz, time() + 86400);

Con esto habremos grabado una matriz en una cookie. Para recuperar un elemento dado al leer la cookie usaremos lo siguiente:

$primerValor = $_COOKIE["matriz"]["primeraClave"];

Una cosa importante. Cuando utilices la función setcookie(), debes colocarla en tu script antes de que se produzca ninguna salida hacia la página. Es decir, antes de cualquier sentencia echo, print(), printf() o cualquier dato visualizable. Además, debe ir antes de ninguna etiqueta HTML. Esto se debe a que esta función trabaja a nivel de cabeceras, un tema sobre el que hablaremos en otro artículo.

SESIONES

La gestión de sesiones es un sistema para almacenar pares nombre-valor en el lado del servidor. El uso de sesiones en lugar del de cookies está más definido cuando las variables deben permanecer a disposición de los scripts que emplea el usuario durante la navegación por distintas páginas del mismo sitio. Supongamos que navegas por un sitio en el que todas las páginas (o muchas de ellas) deben estar personalizadas para cada usuario en concreto. Quizás el ejemplo más clásico y relevante sea una tienda en Internet. El usuario navega por las páginas de distintos productos, viendo cuáles le interesan y seleccionando uno aquí y otro allí para su compra. Los productos elegidos deben recordarse de alguna manera de una página a otra, para que, cuando el usuario cierre la cesta le podamos mostrar una relación y el importe total.

Dado que HTTP es un protocolo sin estados, es decir, no conserva memoria de una página a otra, como ya sabemos, cada compra individual debe almacenarse en un archivo. Sin embargo, es lógico suponer que el usuario no necesita que el recuerdo de esa compra permanezca disponible para usos sucesivos del sitio, así que no es necesario almacenar una cookie en el ordenador del cliente. También podemos considerar otro ejemplo muy clásico: los típicos portales de contactos, donde cada página aparece personalizada con el nombre de usuario de la persona que entra. Así, cuando visita la ficha de otro usuario o le envía un e-mail, queda constancia de quién ha hecho esa visita o quién firma el mensaje.

La forma de almacenar los datos necesarios es mediante unos archivos de servidor que se reconocen porque su nombre empieza con sess_ seguido del número de identificación de la sesión, también llamado número de sesión o session id. El session id se genera de forma aleatoria para cada conexión de un usuario al sitio. Es una cadena formada por un elevado número de dígitos alfanuméricos, de modo que cada usuario, al conectarse, crea un nuevo archivo de sesión, único para él, para esa sesión de trabajo. Cuando abandona el sitio (dirigiéndose a otro, o cerrando el navegador), el archivo ya es innecesario. Si el usuario se vuelve a conectar a nuestro sitio se creará otra sesión.

Para que un script pueda trabajar con sesiones es necesario que incluya, antes de usar ningún dato relativo a la sesión, la función session_start(). Esta función no recibe argumentos y devuelve un valor booleano true, salvo que se haya producido algún error. Tiene dos misiones. Si es la primera vez que se ejecuta en el sitio para una visita en concreto, crea un nuevo archivo de sesión, con un session id exclusivo para ese uso en concreto. Si ya está creada la sesión, la “abre”, es decir, facilita el acceso a las variables que haya registradas.

Para registrar una variable se crea cómo un elemento de una matriz específica de PHP llamada $_SESSION. Cada uno de estos elementos es una variablede sesión que estará disponible, a través de dicha sesión, para otras páginas del sitio. Así, siguiendo con el ejemplo de los idiomas, podemos guardar el idioma elegido por el usuario en una sesión, así:

$_SESSION["idioma"] = "es";

Cuando necesitemos recuperar el idioma en otra página del sitio, lo haremos así:

$idioma = $_SESSION["idioma"];

Se puede regrabar y leer una variable de sessión tantas veces cómo quieras, pero recuerda iniciar cada script con session_start();.

Una cosa importante. Como ya hemos mencionado, la sesión en curso se identifica mediante el session id. Este es un valor que se almacena en una constante del sistema que, por defecto, se llama PHPSESSID. El nombre puede ser cambiado en el archivo de configuración de PHP, aunque mi recomendación es que no lo cambie. La función session_name(), que no recibe argumentos, nos devuelve el nombre de esta constante. Por otra parte tenemos la función session_id(), también sin parámetros, que nos devuelve el valor de la constante de identificación, es decir, el session id de la sesión en curso. Estas dos funciones son muy necesarias ya que, para poder leer las variables almacenadas en un fichero de sesión es necesario que esta constante, con su valor, pase de una página a otra. Para ello, podemos usar un campo oculto de un formulario, que se puede enviar mediante GET o POST, o podemos incluir esta información en la barra de direcciones.

ATENCIÓN. Existe una forma más cómoda de pasar el identificador de sesión de una página a otra del sitio, de modo implícito y transparente al programador. Se trata de activar la directiva session.use_trans_sid en el archivo de configuración. En un artículo posterior aprenderemos lo necesario sobre la configuración de PHP.

Aunque hay más funciones que podemos emplear para optimizar la gestión de sesiones, con las que ya tenemos podemos hacer un uso básico, aunque muy eficiente, de la sesiones. Para comprender su uso hemos creado un sitio ficticio, muy simple, pero que ilustra perfectamente el uso de esta tecnología. El sitio en cuestión responde al esquema de laimagen siguiente:

Esquema de uso de sesiones.

Esquema de uso de sesiones.

En primer lugar, tenemos una página principal, donde le vamos a pedir al usuario dos datos, a modo de ejemplo, que deberán estar disponibles durante toda la navegación por el sitio. He elegido un nombre de usuario y un color para texto. Podríamos haber elegido otros datos. Sólo es un ejemplo. A continuación, tenemos una página donde dichos datos se graban en las correspondientes variables de sesión. Esta página es transparente al usuario, de forma que no tiene por qué percibir nada. Por último, tenemos tres páginas que, en un sitio real, serían de contenidos. En ellas hemos hecho que se muestre el nombre del usuario y, en el color elegido, la página en la que está navegando en cada momento. Cada una de estas páginas tiene sendos enlaces que permiten el acceso a las otras páginas del sitio.

A continuación, vamos a reproducir los listados de las páginas de este sitio. No las cargues en el navegador todavía. Primero veamos los códigos y luego los probaremos. El script usado en la página principal se llama, en este ejemplo, usoDeSesionesInicio.php, y es el siguiente:

Al principio del documento ves el uso de la función session_start() que hemos comentado anteriormente. Lee los comentarios adjuntos que explican el por qué de cada cosa. Observa que no tenemos ningún campo para parsar el identificador de sesión, porque yo ya tengo activado el paso implícito de este parámetro. El formulario carga contra el script cuyo código aparece a continuación y cuyo nombre es paginaCeroDeSesiones.php:

Como ves, este script sólo toma los datos procedentes del formulario anterior y los asigna a las correspondientes variables de sesión. A continuación salta a la primera página de contenidos, cuyo nombre es paginaUno.php:

Observa que se reabre la sesión, con sesion_start() y, a partir de ahí, las dos variables que hemos definido como variables de sesión están disponibles. Los listados de paginaDos.php y paginaTres.php no los reproduzco aquí por su similitud con el que tienes a la vista.

Veamos cómo funciona este conjunto de scripts. En primer lugar, carga en el navegador usoDeSesionesInicio.php. Verás un formulario con dos campos, en el que se te pide tu nombre de usuario y que elijas un color. Al enviar el formulario mediante el botón habilitado al efecto, estos dos datos viajan al servidor, al script paginaCeroDeSesiones.php.

En este script se asignan las variables del formulario a las correspondientes variables de sesión, tras haber iniciado la sesión con session_start(). A partir de ese momento, estas variables quedan disponibles para todas las páginas, mientras dure la visita. El script nos redirecciona automáticamente a paginaUno.php.

Los scripts de paginaUno.php, paginaDos.php y paginaTres.php muestran el nombre del usuario y, en el color elegido, muestran el nombre de la página en la que nos encontramos. Como ves, estos datos se obtienen de las correspondientes variables de sesión. Además, cada página posee dos enlaces que te permiten acceder a las demás.

La función session_destroy() elimina el acceso a la sesión, pero no las variables de la misma, que estarán disponibles de nuevo, si se vuelve a ejecutar session_start(). Si queremos eliminar completamente la sesión (por ejemplo, en una página de cierre o desconexión, empearemos la función session_unset().

     

Un comentario:

  1. Pingback: PHP-TUT-18 La comunicación web » eldesvandejose.com

Deja un comentario

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