• Publicidad

Problema con sesiones en CGI::Session

Aquí encontrarás todo lo que sea específicamente acerca de módulos de Perl. Ya sea que estás compartiendo tu módulo, un manual o simplemente tienes una duda acerca de alguno.

Problema con sesiones en CGI::Session

Notapor pedrete » 2013-02-24 08:13 @384

Hola a todos...

Tengo un problemilla con CGI::Session que me tiene atascado y os agradecería mucho si pudieseis ayudarme un poquillo, por favor...

Tengo una página (login.html) que pide credenciales al usuario. Cuando se introducen, login.pl los chequea, y si están bien, crea una sesión y cede el control a web.pl.

web.pl comprueba lo primero si la sesión es válida. Si lo es, muestra web.html y si no lo es vuelve a login.html.

El problema está en que dentro de web.pl la sesión siempre se ve "empty", por lo que no se avanza... ¿¿¿POR QUÉ???

Curiosamente si el usuario repite el proceso dos veces la segunda vez que se registra, ¡¡¡sí que funciona!!!

login.pl:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use warnings;
  4. use CGI;
  5. use CGI::Session;
  6.  
  7. $cgi=new CGI;
  8.  
  9. if (CredentialsOK($user,$pwd)){
  10.         $sesion=new CGI::Session();
  11.         $sesion->param('userlogged',$user);
  12.         print $sesion->header(-location=>"web.pl");
  13.         $sesion->flush();
  14. }
  15.  else {
  16.         print $cgi->redirect(-uri=>"login.html");
  17. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4



web.pl
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use warnings;
  4. use CGI;
  5. use CGI::Session;
  6. use HTML::Template;
  7.  
  8. $cgi=new CGI;
  9. $sesion=CGI::Session->load($cgi);
  10. $plantilla=HTML::Template->new(filename => 'web.html');
  11.  
  12. $sesion=CGI::Session->load();
  13. if (($sesion->is_expired) || ($sesion->is_empty)) {
  14.         print $cgi->redirect(-uri=>"login.html");
  15. } else {
  16.         print $cgi->header();
  17.         print $plantilla->output();
  18.        }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



¡¡Muchas gracias por adelantado!!

Pedrete.
pedrete
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2011-04-13 09:59 @458

Publicidad

Re: Problema con sesiones en CGI::Session

Notapor explorer » 2013-02-24 09:55 @455

¿Te has dado cuenta de que haces dos llamadas a load(), en web.pl?

No lo he mirado mucho, pero eso sí que lo podrías arreglar.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con sesiones en CGI::Session

Notapor pedrete » 2013-02-24 10:41 @487

¡Uy!, sí...

Mil gracias... Ha sido error del cortar y pegar... Solo hay una llamada...

¿Alguna idea de por dónde ando mal?

Mil gracias de nuevo...
pedrete
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2011-04-13 09:59 @458

Re: Problema con sesiones en CGI::Session

Notapor kidd » 2013-02-24 10:47 @491

A mí me parece que el problema debe de venir en que el navegador está tardando en poner el cookie de la sesión. Yo te sugiero que ajustes la configuración de CGI::Session para poner el dominio correcto, así como usar otro nombre de cookie.
Uriel Lizama Perl programmer fundador de Perl en Español
Perl Programming Language
Avatar de Usuario
kidd
Creador de Perl en Español
Creador de Perl en Español
 
Mensajes: 1166
Registrado: 2003-10-15 16:52 @744
Ubicación: México

Re: Problema con sesiones en CGI::Session

Notapor pedrete » 2013-02-24 10:51 @494

Gracias Kidd...

He comprobado que la cookie llega al navegador pero NO he comprobado que la devuelve al servidor cuando debe... ¡Buena idea! Voy a tirar de Ethereal a ver si la veo...
pedrete
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2011-04-13 09:59 @458

Re: Problema con sesiones en CGI::Session

Notapor pedrete » 2013-02-24 11:31 @521

Kidd,

Gracias a tu sugerencia al analizar el tráfico con Whireshark he encontrado algo muy raro...

La línea:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print $sesion->header(-location=>"web.pl")
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Resulta que envía la cookie al navegador pero no le envía orden de redirección a /web.pl, sino que lo ejecuta localmente en el servidor y SU RESULTADO es lo que envía...

Con permiso del administrador del foro: ¡¡¡LA MADRE QUE LO MATRICULÓ!!! ¡¡¡He perdido 3 días!!!

¡¡¡Gracias de nuevo a ambos!!!
pedrete
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2011-04-13 09:59 @458

Re: Problema con sesiones en CGI::Session

Notapor explorer » 2013-02-24 15:31 @688

A ver, a ver...

Lo de poner un 'location' dentro del header(), no me gusta nada. Debería ser un $session->redirect() (no $cgi->redirect(), como en la línea 16).

Lo que cuentas de que lo ejecuta en el servidor, por una parte me parece lógico, ya que queremos solicitar web.pl, pero antes debe llegar la respuesta HTTP al navegador del usuario. Eso es lo que debe hacer un redirect(). Así que no entiendo que digas que lo ejecuta el servidor web sin avisar antes al navegador... salvo que el servidor web tenga alguna comprobación de redirección antes de entregar el resultado final al navegador. No sé si me he explicado... :?

Un detalle: en un redirect(), hay que poner el URI completo (http://....)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con sesiones en CGI::Session

Notapor pedrete » 2013-02-24 19:34 @856

Gracias, explorer...

Lo del $sesion->header() lo puse porque según indicaciones del manual del CGI:Session esa es la forma de enviar la cookie al navegador...

Saludos...
pedrete
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2011-04-13 09:59 @458

Re: Problema con sesiones en CGI::Session

Notapor explorer » 2013-02-25 09:02 @418

Ya encontré la causa... y me ha dejado sorprendido, porque era algo que desconocía... 8)

La clave está en la línea donde se hace la redirección:

print $sesion->header(-location=>"web.pl");

Bueno, el caso es que lo normal es indicar, en un campo 'Location', una URL absoluta, pero los nuevos navegadores admiten URI relativas, como es este caso.

Y resulta que, efectivamente, el comportamiento del servidor web es muy distinto. A mi me pasa lo mismo que a pedrete: el script web.pl es ejecutado y su salida es el resultado que se envía al cliente, y la URL que sigue mostrando es el de la petición anterior, login.pl.

Después de tres horas de investigación, he descubierto lo que pasa.

La explicación está en el RFC 3875, donde se describe el funcionamiento del protocolo CGI. Lo que nos interesa está justo en la explicación de la cabecera Location (sección 6.3.2.). Esto es lo que dice:
The Location header field is used to specify to the server that the
script is returning a reference to a document rather than an actual
document (see sections 6.2.3 and 6.2.4). It is either an absolute
URI (optionally with a fragment identifier), indicating that the
client is to fetch the referenced document, or a local URI path
(optionally with a query string), indicating that the server is to
fetch the referenced document and return it to the client as the
response.

de lo cual nos quedamos con esta frase:
«Puede ser tanto una URL absoluta (con un identificador de fragmento opcional),
indicando que será el cliente el que solicite el documento referido, o una ruta URI
local (con una cadena de consulta opcional), indicando que será el servidor el que
solicite el documento referido y devolviéndolo al cliente, como respuesta.»


Y esa es la causa: al poner una URI local, es el :arrow: propio servidor :!: el que hace la petición, y la devuelve al cliente como si fuera el contenido de la primera petición. La URL que aparece en el navegador cliente sigue mostrando la dirección anterior, porque el cliente no ha recibido ningún código de estado HTTP 3xx (redirigir a una nueva dirección).

Entonces, este comportamiento lo podemos usar para algún caso especial de redirigir o seleccionar contenidos, pero para el caso de pedrete, no le sirve porque su navegador no llega a recibir la primera cookie (se la come el Apache :) ).

Con los siguientes ejemplos cortos, ya funciona:
Sintáxis: (login.pl) [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. #use warnings;
  3. #use strict;
  4.  
  5. use CGI;
  6. use CGI::Session;
  7.  
  8. my $cgi = CGI->new;
  9.  
  10. my($user) = $cgi->param('user');
  11. my($pass) = $cgi->param('pass');
  12.  
  13. if (CredentialsOK($user,$pass)){
  14.     my $sesion = CGI::Session->new;
  15.     $sesion->param('userlogged',$user);
  16.     print $sesion->header(-location => "http://mi.dominio.com/cgi/web.pl");   # <==
  17.     $sesion->flush();
  18. }
  19. else {
  20.     print $cgi->redirect(-uri=>"/login.html");
  21. }
  22.  
  23. sub CredentialsOK {
  24.     my($user,$pass) = @_;
  25.  
  26.     return ($user eq 'jf'  and  $pass eq 'perl03');
  27. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sintáxis: (web.pl) [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use warnings;
  3.  
  4. use CGI;
  5. use CGI::Session;
  6.  
  7. my $cgi       = CGI->new;
  8. my $sesion    = CGI::Session->load($cgi);
  9.  
  10. if ($sesion->is_expired or $sesion->is_empty) {
  11.     print $cgi->redirect(-uri => "/login.html");                    # mejor si es absoluto
  12. }
  13. else {
  14.     print
  15.         $cgi->header(),
  16.         $cgi->start_html('Titulo'),
  17.         $cgi->p('Bienvenido ' . $sesion->param('userlogged')),      # sí, ¡funciona!
  18.         $cgi->end_html(),
  19.     ;
  20. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El cambio fundamental es poner una URL absoluta dentro de header().

Mejor aún, usar siempre un redirect(), porque siempre enviará un resultado 3xx al navegador:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     print $cgi->redirect("/cgi/web.pl");
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

No se puede escribir $sesion->redirect(...), porque CGI::Session no tiene definido ese método.


Resumen:
  • si queremos realizar un redireccionamiento, lo ideal es usar el método redirect()
  • si no podemos usar un redirect() (?), entonces debemos indicarlo como cabecera 'Location' dentro de un header(). Y aquí hay que pensar en el distinto comportamiento de si es un URL absoluto o un URI relativo

Nunca te acostarás... 8)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con sesiones en CGI::Session

Notapor kidd » 2013-02-25 09:45 @448

Excelente aportación.
Uriel Lizama Perl programmer fundador de Perl en Español
Perl Programming Language
Avatar de Usuario
kidd
Creador de Perl en Español
Creador de Perl en Español
 
Mensajes: 1166
Registrado: 2003-10-15 16:52 @744
Ubicación: México

Siguiente

Volver a Módulos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados