Tienes toda la razón, noa86: la información disponible de CGI::Session es algo escasa.
Por Internet se pueden encontrar algunas referencias y ejemplos. Los que he encontrado:
*
Creating and validating Sessions in Perl CGI*
Creating and validating Sessions in Perl CGI (el mismo autor en otro foro)
Pero el sitio más claro que he encontrado, aunque sorprendente, es el fichero
CGI::Session::CookBook. Digo que es sorprendente porque este fichero no pertenece a la distribución actual de CGI::Session, sino a una anterior, la v3.95.
El caso es que es un poco más claro que el
CGI::Session::Tutorial, pero al ser de una versión anterior, cambian unos pequeños detalles.
He preparado un pequeño ejemplo, que es un resumen del ejemplo mostrado por CGI::Session::CookBook. Realmente, la solución que hay que adoptar es la que indica en ese fichero, no el ejemplo que sigue a continuación.
Using perl Syntax Highlighting
#!/usr/bin/perl
#
# Ejemplo de CGI::Session para login
#
use strict;
use warnings;
use diagnostics;
use CGI::Session;
use CGI ':standard';
use CGI::Carp qw'fatalsToBrowser warningsToBrowser';
## Creamos el objeto CGI
my $cgi = CGI->new();
## Creamos el objeto CGI::Session
my $session = CGI::Session->new("driver:File", $cgi, {'Directory'=>'/tmp/'})
or die CGI::Session->errstr;
## Enviamos la cookie de sesión al usuario
print $session->header;
# Aquí guardaremos el perfil del usuario
my $perfil;
## Inicialización
if ( not $session->param('~registrado') ) { # si el usuario no está registrado
# vemos si se está registrando en este momento
if (my $nombre = $cgi->param('login_nombre')) {
my $passwd = $cgi->param('login_passwd');
# Vemos si es un usuario conocido por nosotros
# si lo es, obtenemos su perfil
if ($perfil = usuario_registrado($nombre, $passwd)) {
# Guardamos el perfil asociado a la sesión
$session->param('perfil', $perfil);
$session->param('~registrado', 1);
}
else { # Es un desconocido, le pedimos que rellene el registro otra vez
presenta_login('Usuario desconocido');
exit;
}
}
else { # No está registrado ni se está registrando
presenta_login('Identifíquese');
exit;
}
}
else { # es un usuario registrado (hay una sesión de él)
# recuperamos el perfil, desde la sesión
$perfil = $session->param('perfil');
}
# A partir de aquí, sabemos qué usuario es, y su perfil
# Podemos presentarle las opciones propias de un usuario registrado
my $nombre = $perfil->{nombre}; # otra forma de hacerlo sería recuperar esta información
my $email = $perfil->{email}; # desde la base de datos, ya que sabemos qué usuario es
if ($cgi->param('Desconectar')) { # caso de que el usuario quiera desconectarse
$session->clear(['~registrado']); # olvidamos que estaba registrado
print # despedida
start_html('Desconexión'),
h1('Desconexión'),
hr(),
p("Adios, $nombre"),
end_html()
;
}
else { # una página normal
print
start_html('Bienvenido'),
h1('Bienvenido'),
hr(),
p("Bienvenido $nombre ($email)"),
hr(),
p(a({-href=>'ficheros.html'},'Ver lista de ficheros')),
p(a({-href=>$cgi->url() . '?Desconectar=1'},'Desconectar')),
end_html()
;
}
# Perfil de un determinado usuario
sub usuario_registrado {
my ($nombre, $passwd) = @_;
# aquí consultaríamos una base de datos, por ejemplo
if ($nombre eq 'JF' and $passwd eq '2010') {
# si es un usuario en nuestra base de datos, recuperamos su perfil
}
return;
}
# Presenta el formulario de entrada
sub presenta_login {
my $titulo = shift;
print
start_html,
h1('Registro de entrada: ' . $titulo),
start_form,
p('Nombre: ' . textfield('login_nombre')),
p('Contraseña: ' . password_field('login_passwd','',8,8)),
p(),
submit('Entrar'),
end_form,
end_html()
;
}
__END__
Coloreado en 0.005 segundos, usando
GeSHi 1.0.8.4
Este programa se puede llamar varias veces. Responderá de distinta manera según responda el usuario. Es un CGI, así que debemos respetar las reglas de programación de los CGI. Como buenos programadores de Perl, somos unos vagos, así que usaremos el módulo CGI y sus funciones de creación de código HTML. Esto tiene la ventaja de hacer el código mucho más corto y claro.
Al principio, de la línea 5 a la 7, ponemos las condiciones de funcionamiento y programación. Nada fuera de lo normal.
Cargamos los módulos necesarios, de la 9 a la 11. Según el CookBook, hay que cargar primero CGI::Session, antes que el módulo CGI. El módulo CGI::Carp nos servirá para ver los errores de programación en la propia pantalla del navegador. Así no tendremos que mirar los ficheros de registro de actividad del servidor web, para buscar esos errores. Cuando el programa funcione bien lo podremos quitar.
El programa comienza en la línea 15, donde crearemos un objeto CGI, que representará la llamada del usuario a este programa.
Después creamos el objeto CGI::Session, en la línea 19. Indicaremos (en este ejemplo), que queremos guardar los datos de la sesión en el directorio /tmp, en forma de ficheros, y que recoja los datos enviados por el usuario a través del objeto $cgi (o dicho de otra manera, $session usará el objeto $cgi para aquellas funciones que en otras ocasiones haríamos solo con el objeto $cgi. Ejemplo: la función header()).
En la línea 22 enviamos al navegador del usuario la cabecera HTTP de respuesta, en la que incluiremos la galleta (
cookie) de sesión. De esta manera, estamos ya creando una sesión, pero solo para tener una primera comunicación con el usuario. No guardamos nada ni sabemos qué usuario es. Es solo que creamos un fichero, en el lado del servidor, donde guardaremos los datos de la futura posible sesión, y una galleta en el lado del cliente.
En la línea 25 declaramos una variable, $perfil, donde guardaremos el perfil del usuario, en caso de que sepamos quién es.
Comenzamos con las pruebas en la línea 28. Ahí miraremos a ver si el el usuario se ha registrado en la sesión correctamente. Para ello, usaremos el objeto $session. El método new() que hemos usado en la línea 18 crea una nueva sesión, en caso de que el usuario se conecte por primera vez, o recupera la sesión que el usuario guarda en su navegador, si no es la primera vez que se conecta. De alguna forma, con estas dos líneas y la 22, tenemos resuelto el tema de crear y recuperar las
cookies de sesión en el lado del cliente.
Para saber si el usuario está registrado en una sesión, la línea 28 intenta recuperar el valor del parámetro '~registrado'. El carácter '~' no significa nada para CGI::Session. Solo tiene significado para nosotros, los programadores: es un recuerdo de que ese parámetro no es uno de los "normales", como por ejemplo el nombre, la contraseña, o el correo electrónico. Éste es una bandera, con valores 0 o 1, indicando si el usuario de esta sesión se ha registrado correctamente.
En caso de que no esté registrado, saltamos a la línea 31, donde comprobaremos si el usuario está respondiendo al formulario de entrada, con su nombre y contraseña. Solo tenemos que leer los parámetros pasados por el formulario, que el objeto $cgi ha recogido.
Teniendo un nombre y una contraseña, pasamos a la línea 36, donde comprobaremos si ese usuario está en nuestra base de datos de usuarios registrados. Y si es así, recuperaremos su perfil.
El perfil es el conjunto de datos del usuario que almacenaremos dentro de la sesión. Pueden ser datos que, aunque podamos recuperar de la base de datos de usuarios, queremos mantener fuera mientras la sesión se mantiene viva. Podría ser información del estado o de la página que está visitando, por ejemplo. Información que no es necesario guardar en la base de datos y con guardarla en el fichero de sesión, nos vale. En este ejemplo, el perfil consistirá en una referencia a un hash, con dos claves: nombre y correo electrónico.
Si hemos conseguido recuperar un perfil de usuario, estamos en la línea 39. Allí, guardaremos el perfil del usuario en el fichero de sesión. Y en la línea siguiente, marcamos la bandera de '~registrado' a 1. La próxima vez que el usuario ejecute este u otro programa parecido, sabrán que la sesión pertenece a un usuario identificado (sabemos quién es) y registrado (coincide su nombre y contraseña con la que tenemos en nuestra base de datos).
En caso de que no encontremos a ese usuario en nuestra base de datos, llegamos a la línea 43, donde le presentaremos el formulario de registro de entrada, y terminamos.
Si el usuario no estaba registrado y tampoco nos estaba enviando sus credenciales, llegamos a la línea 48, donde hacemos lo mismo de antes: formulario de registro y terminamos el programa.
Pero si es un usuario que ya estaba registrado, llegamos a la línea 54, donde recuperamos el perfil del usuario.
Lo que hagamos a partir de esa línea ya depende de nosotros, de lo que queramos enseñarle. En este ejemplo, solo vamos a sacar sus datos, y la opción de 'desconectar' de la sesión.
En las líneas 60 y 61 recuperamos información de su perfil. Y como sabemos quién es, podríamos luego conectarnos a la base de datos y recuperar más información del usuario.
En la línea 63 comprobamos si, el usuario, lo que quiere es desconectar. Si es así, en la línea 64 borramos el parámetro '~registrado' (el usuario no quiere seguir registrado en esta sesión). Y a continuación (líneas 66 y siguientes) le presentamos un adiós. Para ello, usaremos las funciones de generado HTML de CGI, para crear una página HTML sencilla (todas las del ejemplo serán así).
Pero si el usuario no quiere desconectar, llegaremos a la línea 75, donde le presentaremos una página de bienvenida, sus datos, y el enlace de desconexión.
Nada más. Este ejemplo no hace nada más de cara al usuario, pero de la misma manera que hemos creado la bifurcación para la desconexión podríamos crear otras para otras tareas. Y... en ese momento nos daremos cuenta de que quizás sea mejor ir a aprender
CGI::Application, que es mucho más completo que todo esto.
Siguen las subrutinas del programa.
En la línea 88 y siguientes, comprobaríamos si el usuario está en nuestra base de datos, y si es así, devolvemos su perfil. Aquí lo he simplificado a una cuestión muy sencilla (un if()).
Y las líneas 101 y siguientes presentan el formulario de registro de entrada. Nada fuera de lo normal, salvo que recibe un $titulo como parámetro, para informar al usuario de porqué le vuelve a salir el formulario (la línea 43 indica que es un usuario desconocido o ha fallado la contraseña, y la línea 48, que es la primera vez que entra).
Y ya está. Pero recuerda que esta es una de las muchas formas de usar este módulo. Y tampoco es la más óptima. Solo es una demostración. Lo más profesional es usar el módulo
HTML::Template para la generación de las páginas, junto con la opción
associate y el objeto de sesión. De todo esto sí se comenta en el
Tutorial.
Y tampoco es bueno que un solo programa haga todo. Quizás lo mejor sería hacer uno que se encargase de la parte de
login (registro) y luego otros, para cada tarea. En cada uno de ellos pondremos las mismas líneas: recuperar la sesión anterior o crear una nueva. Si el usuario no está registrado, pues lo desviamos a la de registro. De esto hay un par de ejemplos en los primeros enlaces de este mensaje.
El siguiente nivel de perfeccionamiento, es ir directamente a CGI::Application, que es mucho más completo, extenso (y naturalmente, complejo), pero permite crear aplicaciones web más completas (y complejas), pero sin llegar a la solución completa del entorno de trabajo
Catalyst.
Pero aprender CGI::Session está bien, ya que luego nos encontraremos con
CGI::Application::Plugin::Session.