La galleta caduca a la hora del té
Al igual que el "yo" es una simple ilusión psicológica, que asigna una continuidad
a lo que realmente es una sucesión de estados de conciencia (o eso dicen), una
aplicación para Internet no es realmente una aplicación, sino una sucesión de páginas
independientes, que utilizan ingeniosos mecanismos de traspaso de parámetros para dar
también la sensación de continuidad (tranquilícese, el resto no es tan solemne).
En las tiendas virtuales, en particular, el truco más socorrido consiste en asignar
identificadores de conexión para cada "sesión" que inicia un usuario. El servidor
que programamos debe buscar en cada petición que recibe un "parámetro" especial y
recuperar su valor. Si no encuentra el parámetro, asume que se trata de un individuo
que acaba de sentarse frente a su máquina. Entonces crea una nueva sesión, y se las
ingenia para que cada nueva petición de página que haga ese mismo usuario vuelva a
transmitir el identificador asignado. Por supuesto, este no es el lugar para explicar
cómo se logra todo esto.
LAS GALLETAS DE LA SUERTE
De todos modos, la técnica más generalizada entre los programadores con pocas ganas de
trabajar se "reduce" a pasar el identificador de sesión en una cookie. Se trata
de una técnica posible gracias a la complicidad de los navegadores de Internet. Un
servidor, al devolver una página Web a un navegador, puede enviarle también
instrucciones en la cabecera de la respuesta para que éste haga unas "anotaciones"
especiales en un fichero del ordenador del cliente. Esta anotación contiene
un nombre de parámetro, un valor, una fecha de caducidad (sí, tiene que ver con
el título del truco) y un destinatario, que casi siempre es la URL del propio
servidor. Digo que el navegador es cómplice porque, además de hacerle caso al servidor
y crear ese pequeño fichero, cada vez que tiene que pedir algo a la URL del
destinatario se ocupa también de enviarle la información de la cookie. Como
comprenderá, es un mecanismo estupendo para mantener un identificador de sesión
o conexión...
... lo malo es que el usuario puede aguar la fiesta y exigirle a su complaciente
navegador que ignore las malignas sugerencias del servidor, y no acepte cookies.
Por lo tanto, es una política pésima hacer que el funcionamiento de una aplicación
para Internet dependa de las cookies. Afortunadamente, existe una amplia
variedad de técnicas para sustituirlas; las principales son la reescritura de URLs y
la inclusión de campos ocultos. Tampoco es éste el momento de explicaciones.
Ahora llegamos a lo nuestro: de todos modos, es positivo aprovechar las cookies
cuando el usuario no las ha desactivado. Hay que verlas como un recurso que puede que
esté y puede que no. Volvamos al ejemplo de la tienda. La primera vez que se conecta
un señor, le damos un número de sesión, y mientras esa persona siga navegando, cada
nueva página que pida va a estar "infectada" por el identificador asignado. Pero,
¿qué pasaría si el usuario apaga el ordenador y vuelve a encenderlo? Las técnicas
de sustitución de cookies no pueden hacer nada en este caso. Sería algo tan
complicado o imposible de implementar como la transmigración de almas. Y aquí es
donde pueden intervenir las cookies: si el usuario no las ha desactivado,
podemos hacer que nos echen un cabo para identificar la conexión "resucitada".
Lo único que nos quedaría es tomar una decisión sin mayor importancia: ¿cuánto tiempo
le daremos de vida a la cookie con el número de conexión? Si nadie compartiese
su ordenador con otras personas, no había problemas en otorgarle una vida eterna a la
galletita de la suerte; claro, los que se ven obligados a compartir ordenador pondrían
el grito en el cielo... Lo normal es tener una variable de configuración con el número
de minutos de vida de la cookie. La fecha de caducidad puede indicarse durante
la creación de la misma:
with Response.Cookies.Add do
begin
Name := 'CONNID';
Value := IntToStr(FIDConexion);
Expires := Now + FMinutos / (24 * 60); // ¡Aquí hay gato encerrado!
end;
Expires es una propiedad de tipo TDateTime. Recuerde que este tipo
representa los tiempos como fracciones de un día. Como un día tiene 24 horas, y
cada hora 60 minutos, hay que dividir los minutos por esa cantidad para obtener la
fracción del día que representan, y sumárselo al resultado de la función Now,
que como sabemos devuelve la hora de...
UNIVERSAL TIME COORDINATES
...vale, acepto que a veces soy un poco idiota. Now devuelve la hora
local, que en este caso es la hora nacional. Pero usted no tiene por qué
vivir en el mismo huso horario que yo. Por este motivo, las fechas en HTTP suelen
especificarse de acuerdo a un sistema de referencia global. Y ese sistema
global se llama Universal Time Coordinates, que se puede abreviar como UTC.
Para todos los propósitos prácticos, el sistema UTC utiliza la hora del meridiano de
Greenwich (de aquí, lo de "la hora del té"), pero ignorando los desplazamientos
provocados por el horario de verano. UTC especifica además, para su representación
interna, un "momento cero": el 1 de enero del 1970.
Como comprenderá, si asignamos la fecha de caducidad utilizando Now, estaremos
introduciendo un intervalo espurio, y las cookies caducarán antes o después, en
dependencia del meridiano local. En España, en el mes de mayo, por ejemplo, sería dos
horas después del momento deseado.
¿Cómo obtener la hora actual en el sistema UTC? Es muy fácil, porque el API de Windows
nos ofrece la función GetSystemTime. He aquí una versión de Now que puede sernos
útil:
function UTCNow: TDateTime;
var
S: TSystemTime;
begin
GetSystemTime(S);
Result := EncodeDate(S.wYear, S.wMonth, S.wDay) +
EncodeTime(S.wHour, S.wMinute, S.wSecond, S.wMilliseconds);
end;
Como es lógico, hay que modificar el fragmento de código donde se envía la
cookie:
with Response.Cookies.Add do
begin
Name := 'CONNID';
Value := IntToStr(FIDConexion);
Expires := UTCNow + FMinutos / (24 * 60); // ¡Ahora sí!
end;
|