Desde otros métodos, ejecutados por CGI::Application, se supone que antes habrá sido llamado cgiapp_init() (esto lo puedes comprobar poniendo un print a un archivo o al archivo de registro (log) de actividad. No lo hagas hacia la salida estándar).
Esta es una cgiapp_init() mía:
Using perl Syntax Highlighting
## Inicialización ----------------------------------------------------------------
sub cgiapp_init() {
my $self = shift;
$query = $self->query; # creamos/leemos un objeto CGI
$query->charset('UTF-8'); # salida siempre en utf8
# Problemas: cachea demasiado: no se da cuenta de que hay un usuario registrado
# $self->header_add( -expires => '+1m' ); # caché en el navegador del usuario
# Caso de que sea una confirmación,
# el usuario nos manda la id de sesión con la que se registró
if ($self->get_current_runmode() eq 'confirmacion') {
my $sid = $self->param('n');
if ($sid) {
$query->param(-name => CGI::Session->name, -value => $sid, -override => 1);
}
}
else { # en el resto de modos, es necesario abrir la hoja
$xls = ReadData($BASE_DE_DATOS, cells => 1, attr => 0);
die "ERROR: Base de datos no encontrada" if not $xls;
%xls_hojas = %{$xls->[0]{sheet}}; # Relación hojas -> índices
}
# configuración de la sesión de usuario
$self->session_config(
CGI_SESSION_OPTIONS => [ 'driver:File', $query, {Directory => "$DIRECTORIO_WEB/sesiones"} ],
DEFAULT_EXPIRY => '+90d',
COOKIE_PARAMS => { -expires => '+90d' },
SEND_COOKIE => 1,
);
$session = $self->session;
$self->dbh_config($db_dsn, $db_user, $db_pass);
}
Coloreado en 0.004 segundos, usando
GeSHi 1.0.8.4
Lo importante es esto:
- en la línea 78 guardo el objeto CGI en $query. Allí estará todo lo que me llega del usuario, incluidas las galletas
- las líneas 86 a 91 son algo especial: en caso de que la llegada a nuestra web haya sido porque el usuario ha pulsado en el enlace de confirmación que le enviamos por correo, en la propia URL viene un parámetro, que coincide con el número de sesión creado por la llamada a CGI::Session en la primera visita. Entonces, si se trata de una confirmación (86), leemos ese valor (87), y modificamos el objeto CGI con ese número de sesión (89). Esto es importante: si no hiciéramos esto, en el valor de sesión que -posiblemente- hemos leído antes en la 78, podríamos tener un número de sesión distinto del que el usuario usó en su primera visita. Y necesitamos que sea el mismo, porque grabé en esa sesión sus datos de registro. La línea imita la creación de una galleta con el nombre de CGISESSID, y de valor el que nos ha mandado el usuario al pulsar el enlace
- luego, en la línea 99 a 104 creamos las condiciones de cómo son las sesiones. Y la clave está en la inclusión de $query: si no hay ninguna galleta, no hay número de sesión, así que se crea una nueva. Pero si hay un parámetro llamado CGISESSID, entonces no se crea una nueva sesión, sino que se accede a la antigua.
- línea 106 : obtenemos el objeto CGI::Session. Lo metemos en una variable global para usarla en el resto del programa
Entonces, en tu programa, debes asegurarte que el método que quiere acceder a una determinada sesión, ha conseguido 1) recuperar el número de sesión desde el usuario, bien a través de la URL o con una galleta, y 2) que coincide con su número de sesión anterior.
Pufff... no creas que esto es sencillo: he tenido que dedicarle horas a entender el flujo de datos, y a tener varias ventanas abiertas, mostrando el listado de archivos de sesión, y qué es lo que contenían, para comprobar que todo funcionaba bien...
Eso sí: cuando te lo aprendes, luego hacer sitios web basados en este entorno de trabajo se hace más fácil (bueno, hoy en día hay soluciones más condensadas).
¡Ah!, y queda por hacer un script que se dedique exclusivamente al borrado de las sesiones caducadas...
Using perl Syntax Highlighting
#!/usr/bin/perl
#
# Purgado de sesiones caducadas.
#
# Se hace aquí para no cargar la CPU con el cgi de la aplicación.
# Se ejecuta desde un cron.
#
# Joaquín Ferrero. 20110802
#
use CGI::Session;
CGI::Session->find(
'driver:File',
sub {},
{
Directory => '/home/sitioweb/sesiones',
}
);
__END__
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4