2011-03-29 14:30 @646 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
Lo tengo ahora mismo así Using perl Syntax Highlighting $dbh = DBI->connect("DBI:mysql:$database:localhost",$user,$passwd) or die("Can't connect to db: ",$dbh->errstr);
my $session = CGI::Session->new(); #esta linea no la puedo eliminar por completo porque si no me da error print $session->header, ya que me dice que session no esta definido.
## Enviamos la cookie de sesión al usuario
print $session->header;
my $perfil;
## Inicialización
if ( not $session->param('~registrado') ) { # si el usuario no está registrado
$session = CGI::Session->load("driver:MySQL", $cgi, {Handle=>$dbh}) or die CGI::Session->errstr();
if ( $session->is_expired){
print $cgi->start_html(),
$cgi->p("Your session timed out! Refresh the screen to start new session!"),
$cgi->end_html();
exit(0);
}
if ($session->is_empty){
$session = $session->new("driver:MySQL", $cgi, {Handle=>$dbh}) or die $session->errstr;
$session -> expire('+1m');
}
Sigue con el mismo problema, yo creo. Sigue sin salirme el mensaje de error... no entra en el if() de is_expired() pero sí en el de is_empty().
|
2011-03-29 16:53 @745 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
Ya entiendo lo que me quieres decir, pero si hago lo que me dices me sale un error: Using text Syntax Highlighting load(): couldn't thaw() data using CGI::Session::Serialize::default: at /var/www/cgi-bin/wei/privat/wei.interfazedicion.perl es decir, por lo que entiendo yo, ese error sale porque como no está creado CGI::Session (new()) no se puede hacer load().
|
2011-03-29 17:02 @751 |
|
|
 |
explorer
Administrador
|
Registrado: 2005-07-24 18:12 @800 Ubicación: Valladolid, España Mensajes: 10249
|
|
|
Re: Control de acceso CGI::Session
|
Using perl Syntax Highlighting my $session = CGI::Session->load("driver:MySQL", $cgi, {Handle=>$dbh}) or die CGI::Session->errstr();
Sacado de la documentación de load() en CGI::Session.
_________________ JF^D Perl programming
|
2011-03-29 17:49 @784 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
|
He reiniciado el ordenador y me ha dejado de dar ese error.
Pero poniéndolo como hemos comentado ahora sigue sin funcionarme is_expired(), y además me ha dejado de funcionar bien las sesiones, ya que cada vez que ejecuto el cgi tengo que iniciar sesión, como si no me la guardara, y cuando tenía puesto el new() una vez iniciada sesión no tenía que volver a iniciar a no ser que cerrara el navegador o expirara el tiempo...
|
2011-03-29 18:40 @820 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
Ahora mismo tengo el código así. ¿Sería correcto como he programado lo referente a control de sesiones? Sigo sin saber por qué no me funciona el método is_expired(). Necesito una solución... Using perl Syntax Highlighting #!/usr/bin/perl
require("wei.conf.perl");
use DBI;
use CGI::Session;
use CGI ':standard';
use CGI::Carp qw'fatalsToBrowser warningsToBrowser';
my $cgi = CGI->new();
$dbh = DBI->connect( "DBI:mysql:$bd:localhost", $user, $passwd )
or die( "Can't connect to db: ", $dbh->errstr );
my $session = CGI::Session->load( "driver:MySQL", $cgi, { Handle => $dbh } )
or die CGI::Session->errstr();
if ( $session->is_expired ) {
print $cgi->start_html(),
$cgi->p("Your session timed out!"),
$cgi->end_html();
exit(0);
}
if ( $session->is_empty ) {
$session = CGI::Session->new( "driver:MySQL", $cgi, { Handle => $dbh } );
$session->expire(10);
}
print $session->header;
if ( not $session->param('~registrado') )
{ # si el usuario no está registrado
if ( my $nombre = $cgi->param('login_nombre') ) {
my $passwd = $cgi->param('login_passwd');
if ( usuario_registrado( $nombre, $passwd ) ) {
$session->param( 'nombre', $nombre );
$session->param( '~registrado', 1 );
}
else {
presenta_login('Usuario desconocido');
exit;
}
}
else {
presenta_login('Identifiquese');
exit;
}
}
if ( $cgi->param('Desconectar') ) {
$session->clear( ['~registrado'] );
print
start_html('Desconexión'),
h2('Se ha desconectado'),
hr(),
p("Adios, $nombre"),
end_html();
}
else {
print
start_html('Bienvenido'),
h2('Bienvenido'),
hr(),
p( "Bienvenido", $session->param('nombre') ),
hr(),
p( a( { -href => $cgi->url() . '?Desconectar=1' }, 'Desconectar' ) ),
end_html();
#continuación de pagina.
}
sub usuario_registrado {
...;
}
sub presenta_login {
...;
}
Última edición por noa86 el 2011-03-31 14:19 @638, editado 1 vez en total
|
2011-03-31 08:17 @386 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
|
¿Nadie sabe por qué puede ser que no me funcione is_expired?
|
2011-03-31 10:19 @471 |
|
|
noa86
Perlero Nuevo
|
Registrado: 2010-11-15 14:43 @655 Mensajes: 93
|
|
|
Re: Control de acceso CGI::Session
|
|
Lo que necesito es que cuando salga de la sesión porque el tiempo ha expirado, muestre un mensaje "Su tiempo ha expirado, ingrese de nuevo".
¿Hay alguna otra manera de hacer eso a parte del método is_expired() que no me funciona?
¿Alguien puede ayudarme por favor?
Última edición por noa86 el 2011-04-03 13:30 @604, editado 1 vez en total
|
2011-03-31 22:37 @984 |
|
|
 |
explorer
Administrador
|
Registrado: 2005-07-24 18:12 @800 Ubicación: Valladolid, España Mensajes: 10249
|
|
|
Re: Control de acceso CGI::Session
|
Texto muy largo, que solo interesa el último ejemploEl problema es el siguiente: Cuando tu marcas un tiempo de expiración con expire(), ese tiempo se marca tanto en el fichero de sesión que se guarda en la base de datos, como en el tiempo de expiración de la cookie (galleta) que se manda al usuario. Si el usuario accede dentro del tiempo asignado, aparecerá como registrado, pero si deja pasar ese tiempo (desde la última vez que se accedió al sistema), la galleta de su navegador habrá caducado, por lo que no se transmitirá al cgi... Para el cgi será como si se hubiera conectado un nuevo usuario, por lo que creará una nueva sesión con new(). En resumen: nunca nos enteraremos de si la sesión ha caducado, porque el usuario nunca nos transmitirá una cookie caducada (bueno, 'puede' darse el caso, alguna vez... depende de los relojes de cada ordenador). Así que, por defecto, siempre recibiremos peticiones de sesiones conocidas o peticiones de nuevas sesiones. Nunca veremos que la función is_expired() sea cierta. Este ejemplo funciona así: Using perl Syntax Highlighting #!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use CGI qw':standard';
use CGI::Session;
use CGI::Carp qw'fatalsToBrowser warningsToBrowser';
chdir '/home/explorer/public_html'; # directorio de trabajo
my $cgi = CGI->new; # creamos el objeto CGI
my $session # creamos el objeto CGI::Session
= CGI::Session->load(
"driver:file",
$cgi,
{Directory => './sesiones'}
);
die "ERROR: \$session indefinida\n" if not defined $session;
if ($session->is_expired) { # ¿la sesión ha expirado?
print
$session->header,
$cgi->start_html,
cabeceras_http(),
$cgi->p("Su sesión ha expirado. Identifiquese de nuevo:"),
formulario(),
$cgi->end_html,
;
terminar();
}
if ($session->is_empty) { # ¿la sesión está vacía?
$session = $session->new( # creamos una nueva
"driver:file",
$cgi,
{Directory => './sesiones'}
) or die "ERROR en la creación de nueva sesión: " .$session->errstr;
$session->expire('60'); # le dejamos estar 60 segundos
}
# vemos si se está autenticando
my $usuario = $cgi->param('login_nombre') || '';
my $passwd = $cgi->param('login_passwd') || '';
if ($usuario and $passwd and usuario_verificado($usuario, $passwd)) {
$session->param('~registrado', 1);
$session->param('nombre', $usuario); # guardamos su nombre
}
if (! $session->param('~registrado')) { # ¿es un usuario registrado?
print # No. Presentamos la página de registro
$session->header,
$cgi->start_html,
cabeceras_http(),
$cgi->p("Identifiquese:"),
formulario(),
$cgi->end_html,
;
terminar();
}
# Llegamos aquí cuando el usuario está registrado e identificado
print # sí, presentamos una página normal
$session->header,
$cgi->start_html,
cabeceras_http(),
$cgi->p('Gracias por su visita, ' . $session->param('nombre'). '. Dispone de 60 segundos.'),
$cgi->end_html,
;
## Fin del programa
terminar();
### Subrutinas
sub usuario_verificado { # consulta si el usuario es real
return $_[0] eq 'JF' and $_[1] eq 'c12';
}
sub formulario { # presenta un formulario muy simple
return
$cgi->start_form,
'Nombre: ',
$cgi->textfield('login_nombre'), br,
'Passwd: ',
$cgi->password_field('login_passwd'), br,
$cgi->submit,
$cgi->end_form,
;
}
sub cabeceras_http {
return
$cgi->p(
join $cgi->br, map { "$_ : " . $cgi->http($_) } sort $cgi->http()
)
;
}
sub terminar {
$session->flush();
CGI::Session->find('driver:file', sub {}, {Directory => './sesiones'} ); # Purgamos sesiones caducadas
exit(0);
}
Básicamente: - Creamos el objeto CGI y el objeto CGI::Session, a partir del load()
- Si la sesión ha expirado, se le presenta un mensaje de aviso y el formulario de entrada, y termina
- Si la sesión está vacía, se crea una nueva sesión, con un tiempo de expiración de 60 segundos
- Si el usuario nos está mandando las credenciales, comprobamos su validez
- Si es un usuario valido (nos da nombre y contraseña) y verificado (le reconocemos), entonces lo marcamos con un parámetro llamado '~registrado' igual a 1 (el nombre del parámetro da igual)
- Si el usuario no está registrado, entonces le presentamos el formulario de entrada y terminamos
- Si sí lo está, le presentamos el resto del web (en este caso, una página sencilla)
- Y terminamos
Como detalles importantes: - Este ejemplo difiere del tuyo en que estoy usando sesiones basadas en ficheros en disco, en lugar de usar una base de datos, pero el funcionamiento de la sesión es igual
- A terminar() se le llama desde distintos puntos, pues tiene varias tareas que hacer: hace un flush(), que, realmente, en este ejemplo, no es necesario, porque el propio CGI::Session lo llamaría de forma automática, al salir del programa. Caso distinto es si guardáramos la sesión en una base de datos, como es tu caso: si la variable que almacena la conexión a la base de datos sale del contexto en que fue creada, la sesión quizás no pueda grabarse bien en la base de datos. Por ello se recomienda llamar a flush() antes de terminar el programa, en un sitio seguro dentro del programa, donde estemos seguros que aún tenemos control de la $session. Y una cosa más que hace terminar(): elimina las sesiones caducadas, con la ayuda de find(). Si no lo hiciéramos, se irían acumulando indefinidamente en disco o en la base de datos.
- cabeceras_http() es una función de apoyo, para ver las cabeceras HTTP que el usuario nos manda a nuestro CGI.
En situaciones normales, esto es precisamente lo que queremos: mantener la sesión con el usuario, o pedirle que se autentifique. Así que este ejemplo vale para la gran mayoría de sitios web en los que queremos llevar un control de los usuarios que entran. Y la expiración del tiempo la da la propia expiración de la cookie que NO se transmite desde el usuario a nuestro cgi. Ahora bien... este programa no hace lo tu que quieres... Tu quieres que el programa cgi reconozca al usuario para decirle que su sesión ha expirado. Eso implica que: el usuario se debe conectar a nuestro cgi con una cookie de sesión, y que encontremos que esa sesión ha caducado en nuestro sistema. Fíjate que lo que estás pidiendo es muy especial: pocos sitios web lo tienen implementado así... la mayoría usan la primera técnica: si la cookie caduca, es que la sesión caduca. Otros sitios web utilizan trucos para hacer lo que quieres. Uno de ellos es el de transmitir dos cookies. Una de ellas contendrá un identificador con el que relacionaremos el nombre del usuario, cuando se registre. Y la otra nos servirá para el control del tiempo de sesión. Así, cuando el usuario lleve un tiempo sin hacer nada en nuestro sitio web, la segunda cookie caducará y no se transmitirá, pero la primera sí se transmitirá (no caducará porque le hemos dado una fecha de expiración muy grande, como por ejemplo, 1 de abril del 2030). Entonces, ¿qué ocurre? Pues que el programa que recibe la primera cookie sabe quién es (el usuario que se conecta), pero como no recibe la cookie de control de tiempo, entonces sabe que la sesión ha expirado, por lo que mostrará un aviso al usuario (sabe quién es y sabe que la sesión ha caducado). No sé si este es el comportamiento que quieres hacer o te vale con el primero, el básico. Si no quieres complicarlo, te recomiendo que te olvides de todo el tema de load() y de is_expired(). Simplemente, con hacer un new() al principio para crear la sesión, CGI::Session se dará cuenta de cuándo es una nueva sesión o de una sesión ya iniciada por el usuario. Solo te quedará hacer un expire() para marcar cuánto tiempo queremos que dure la sesión, y listo: si el usuario se conecta más allá del tiempo indicado, no transmitirá la cookie de sesión, así que para nosotros será como si se conectara de nuevo. ¿Te vale así, o prefieres el segundo comportamiento? ¿Aquel en el que sabemos quién es, aunque haya caducado la sesión? Si queremos que se comporte de la segunda manera, tenemos que trabajar de forma distinta: Using perl Syntax Highlighting #!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use CGI qw':standard';
use CGI::Cookie;
use CGI::Session;
use CGI::Carp qw'fatalsToBrowser warningsToBrowser';
my $tiempo_sesion = '10s'; # Tiempo que dura la sesión
chdir '/home/explorer/public_html'; # directorio de trabajo
my $cgi = CGI->new; # creamos el objeto CGI
my $session # creamos el objeto CGI::Session
= CGI::Session->load(
"driver:file",
$cgi,
{Directory => './sesiones'}
);
die "ERROR: \$session indefinida\n" if not defined $session;
my $cookie;
if ($session->is_expired) { # ¿la sesión ha expirado?
print
$cgi->header(),
$cgi->start_html,
cabeceras_http(),
$cgi->p("Su sesion ha expirado. Identifiquese de nuevo:"),
formulario(),
$cgi->end_html,
;
terminar();
}
if ($session->is_empty) { # ¿la sesión está vacía?
$session = $session->new( # creamos una nueva
"driver:file",
$cgi,
{Directory => './sesiones'}
) or die "ERROR en la creación de nueva sesión: " .$session->errstr;
$session->expire($tiempo_sesion); # Tiempo de expiración de la sesión
}
# Creamos una cookie con un tiempo de expiración superior al de sesión (una hora)
$cookie = $cgi->cookie( -name => $session->name, -value => $session->id, -expires => '+1h');
# vemos si se está autenticando
my $usuario = $cgi->param('login_nombre') || '';
my $passwd = $cgi->param('login_passwd') || '';
if ($usuario and $passwd and usuario_verificado($usuario, $passwd)) {
$session->param('~registrado', 1);
$session->param('nombre', $usuario); # guardamos su nombre
}
if (! $session->param('~registrado')) { # ¿es un usuario registrado?
print # No. Presentamos la página de registro
$session->header(-cookie=>$cookie),
$cgi->start_html,
cabeceras_http(),
$cgi->p("Identifiquese:"),
formulario(),
$cgi->end_html,
;
terminar();
}
# Llegamos aquí cuando el usuario está registrado e identificado
print # sí, presentamos una página normal
$session->header(-cookie=>$cookie),
$cgi->start_html,
cabeceras_http(),
$cgi->p('Gracias por su visita, ' . $session->param('nombre'). ". Dispone de $tiempo_sesion."),
$cgi->end_html,
;
## Fin del programa
terminar();
### Subrutinas
sub usuario_verificado { # consulta si el usuario es real
return $_[0] eq 'JF' and $_[1] eq 'c12';
}
sub formulario { # presenta un formulario muy simple
return
$cgi->start_form,
'Nombre: ',
$cgi->textfield('login_nombre'), br,
'Passwd: ',
$cgi->password_field('login_passwd'), br,
$cgi->submit,
$cgi->end_form,
;
}
sub cabeceras_http {
return
$cgi->p(
join $cgi->br, map { "$_ : " . $cgi->http($_) } sort $cgi->http()
)
;
}
sub terminar {
$session->flush();
CGI::Session->find('driver:file', sub {}, {Directory => './sesiones'} ); # Purgamos sesiones caducadas
exit(0);
}
Esta versión es casi idéntica a la anterior, pero hay unos pequeños cambios. Estos son los más importantes: - Línea 7: importamos el módulo CGI::Cookie
- Línea 26: declaramos la variable global $cookie
- Línea 51: creamos una cookie, usando el mismo nombre y el mismo id de sesión que el que utiliza CGI::Session, pero con la diferencia de que esta cookie tiene un tiempo de expiración mucho más largo: una hora
- Línea 65 y 78: a la hora de enviar las cabeceras, enviamos nuestra propia $cookie. En realidad, lo que estamos haciendo es "machacar" la cookie que crea CGI::Session, con un tiempo de expiración marcado en la línea 48, por nuestra propia $cookie, con un tiempo de expiración de 1 h.
El resultado es el siguiente: el usuario se registra de forma normal. La cookie almacenada en su equipo expirará en una hora, pero la sesión, en el servidor, expirará mucho antes (10 s como ves en la línea 11). Si el usuario deja pasar esos diez segundos y vuelve a conectarse a nuestro cgi, su navegador transmitirá la cookie (no ha pasado una hora, por lo que no ha caducado). CGI::Session verá (en el load() de la línea 18) que sí hay una sesión correspondiente a la cookie que está recibiendo, pero, como han pasado más de diez segundos, la marca como expirada, y elimina la sesión (en el ejemplo, al ser ficheros, lo que hace es borrar el fichero de sesión). El programa entra por el if() de la línea 29 (is_expired() da verdadero), pero toda la información de la sesión se ha perdido (todos los parámetros almacenados en la sesión). Sale el aviso de que ha expirado y que se registre de nuevo. Si el usuario, en vez de registrarse, recarga la página, entonces load() ya no encontrará una sesión correspondiente a la cookie que está recibiendo, porque borró la sesión hace un momento. Entonces, lo que ve el usuario es el mensaje directo de "Identifíquese", como si nunca hubiera entrado. Bueno, esta es una forma de hacerlo, que se aproxima a lo que quieres hacer, pero no deja de ser una pequeña chapuza: estamos sobreescribiendo una cookie que ha fabricado CGI::Session por una fabricada por nosotros. Esto podría no funcionar si el autor de CGI::Session hace algún cambio importante en el código. Hay una solución mejor: hacer que sea un parámetro de la sesión el que lleve el control del tiempo de expiración: Using perl Syntax Highlighting #!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use CGI qw':standard';
use CGI::Session;
use CGI::Carp qw'fatalsToBrowser warningsToBrowser';
my $tiempo_sesion = '+1d'; # Tiempo que dura la sesión (máximo)
my $tiempo_login = '+10s'; # Tiempo que dura la sesión (identificado)
chdir '/home/explorer/public_html'; # directorio de trabajo
my $cgi = CGI->new; # creamos el objeto CGI
my $session # creamos el objeto CGI::Session
= CGI::Session->new('driver:file', $cgi, {Directory => './sesiones'});
die "ERROR: \$session indefinida\n" if not defined $session;
if ($session->is_new) { # ¿es una nueva sesión?
$session->expire($tiempo_sesion); # Tiempo de expiración de la sesión (todo el día)
print # Presentamos la página de registro
$session->header,
$cgi->start_html,
cabeceras_http(),
$cgi->p("Identifiquese:"),
formulario(),
$cgi->end_html,
;
terminar();
}
my $usuario = $cgi->param('login_nombre') || ''; # Vemos si se está registrando
my $passwd = $cgi->param('login_passwd') || '';
if ($usuario and $passwd and usuario_verificado($usuario, $passwd)) {
$session->param('~registrado', 1); # Lo marcamos como registrado
$session->expire('~registrado', $tiempo_login); # Tiempo que dura la sesión (login)
$session->param('nombre', $usuario); # Guardamos su nombre
}
if (! $session->param('~registrado')) { # ¿Ha pasado el tiempo de sesión login?
my $usuario = $session->param('nombre') || ''; # Recuperamos su nombre
$usuario = ", $usuario" if $usuario;
print
$cgi->header(),
$cgi->start_html,
cabeceras_http(),
$cgi->p("Su sesion ha expirado$usuario. Identifiquese de nuevo:"),
formulario(),
$cgi->end_html,
;
terminar();
}
# Llegamos aquí cuando el usuario está registrado e identificado
print # presentamos una página normal
$session->header,
$cgi->start_html,
cabeceras_http(),
$cgi->p('Gracias por su visita, ' . $session->param('nombre'). ". Dispone de $tiempo_login mas."),
$cgi->end_html,
;
## Fin del programa
terminar();
### Subrutinas
sub usuario_verificado { # consulta si el usuario es real
return $_[0] eq 'JF' and $_[1] eq 'c12';
}
sub formulario { # presenta un formulario muy simple
return
$cgi->start_form,
'Nombre: ',
$cgi->textfield('login_nombre'), br,
'Passwd: ',
$cgi->password_field('login_passwd'), br,
$cgi->submit,
$cgi->end_form,
;
}
sub cabeceras_http {
return
$cgi->p(
join $cgi->br, map { "$_ : " . $cgi->http($_) } sort $cgi->http()
)
;
}
sub terminar {
$session->flush();
CGI::Session->find('driver:file', sub {}, {Directory => './sesiones'} ); # Purgamos sesiones caducadas
exit(0);
}
Incluso queda más corto Los cambios más importantes son: - Línea 18. Quitamos load() y lo cambiamos a new(). Él se encargara, o bien de cargar una sesión anterior, o de crear una nueva
- Línea 22. Si la sesión es nueva, pues le damos un tiempo de expiración muy largo (todo el día). Este es el valor de expiración tanto para la sesión como para la cookie que se envía al usuario (y que nos devuelve). Le presentamos el formulario de registro al usuario y terminamos
- Línea 42. (el truco) Le damos al parámetro '~registrado' un valor de 1 (podría ser otro valor mejor), y un tiempo de expiración de $tiempo_login. Este es el tiempo que queremos que esté activa la sesión de usuario sin que tenga que identificarse otra vez
- Línea 47. Preguntamos si está registrado o no. '~registrado' indicará si, además de estar identificado en el sistema, ha caducado o no la sesión. Su no-presencia indicará que ha caducado, por lo que le avisamos al usuario, y terminamos
El resto es igual a lo que teníamos antes. Espero que ahora haya quedado claro. Falta la parte de borrar la sesión por indicación del usuario (delete()), pero es cuestión de poner otro if() en el lugar adecuando (por ejemplo, antes de ver si se está registrando).
_________________ JF^D Perl programming
|
| Reglas del Foro |
No puedes abrir nuevos temas en este Foro No puedes responder a temas en este Foro No puedes editar tus mensajes en este Foro No puedes borrar tus mensajes en este Foro No puedes enviar adjuntos en este Foro
|
|
Socializa |
 |
|