• Publicidad

CGI::Application y CGI::Session

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

CGI::Application y CGI::Session

Notapor noa86 » 2011-04-12 13:45 @615

Hola, tengo un dilema...

Tengo una aplicación CGI en la que se crean sesiones, y una vez iniciada una sesión, hay un enlace a una página nueva que estoy intentando crearla con CGI::Application. Para poder configurar esta última con la sesión cargada anteriormente, ¿cómo tengo que programarlo?

En el setup tengo, a parte de el resto de configuraciones:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $self->dbh_config(
  2.         "dbi:mysql:database=$bd:host=$host",
  3.         "$user",
  4.         "$pass"
  5.     );
  6.  
  7.     $self->session_config(
  8.                 CGI_SESSION_OPTIONS => [ "driver:mysql:serializer:Storable",
  9.                         $self->query,
  10.                         {Handle=>$self->dbh}
  11.                 ]);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


y en el cgiapp_prerun
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     $self = shift;
  2.    $q = $self->query();
  3.    my $session = $self->session();
  4.    unless ( $self->session->param('registrado') ) {
  5.       print $q->redirect('http://www.google.com');
  6.    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


y

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub cgiapp_postrun {
  2.     $self = shift;
  3.     $self->session->flush if $self->session_loaded;;
  4.  }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Con esto quiero que si no ha sido registrado se redirija a Google pero si está identificado en la sesión creada en el cgi anterior que muestre otra página que en este caso es una plantilla HTML.

¿Qué hago mal, qué me falta?
noa86
Perlero nuevo
Perlero nuevo
 
Mensajes: 93
Registrado: 2010-11-15 14:43 @655

Publicidad

Re: CGI::Application y CGI::Session

Notapor explorer » 2011-04-12 15:09 @672

Pues creo que falta: todo el tema de rellenar la plantilla, en caso de estar registrado.

Y en caso de no estar registrado, en lugar de usar el redirect() del paquete CGI, es mejor que veas y uses el módulo CGI::Application::Plugin::Redirect.

Entonces, con un return $self->redirect('http://www.google.com'); , bastaría. Observa que es return(), no print(): si queremos hacer un redirect(), queremos devolver rápidamente el control, y que se encargue CGI::Application de hacer el redirect().
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: CGI::Application y CGI::Session

Notapor noa86 » 2011-04-12 15:45 @698

La plantilla la tengo creada y la cargo en el método sub start que es un run_mode, sin validar las sesiones la página se me crea correctamente. Pero cuando pongo la configuración de la sesión y validar si está registrado o no, me aparece un mensaje de error del prerun():

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Error executing class callback in prerun stage: Storable binary image v18.68 more recent than I am (v2.8) at blib/lib/Storable.pm
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Y la verdad, que no sé la razón, porque por lo que entiendo yo, es que si está registrado, saltaría el redirect() y se ejecutaría la función start(), ¿no? O tengo que llamarla.

En prerun() tengo lo que he comentado antes, aunque he cambiado la línea de redirect() como me has dicho.
noa86
Perlero nuevo
Perlero nuevo
 
Mensajes: 93
Registrado: 2010-11-15 14:43 @655

Re: CGI::Application y CGI::Session

Notapor explorer » 2011-04-12 16:04 @711

El error dice que el módulo Storable (el responsable de guardar estructuras Perl a disco, y luego recuperarlas. Vamos, lo que se conoce hoy en día como serialización de datos), ha encontrado que la estructura de datos que ha encontrado en disco es de una versión (v18.68) anterior a la versión que es él mismo (v2.8).

Me suena que tienes mezclados módulos de distintas versiones. O que hay algo grabado en disco que está en una versión anterior (lo comentado antes).

Pero... esto me llama mucho la atención... no creo que CGI::Application grabe nada en disco... salvo quizás grabar la sesión.

Te recomiendo que entres en el directorio (o bases de datos) de sesiones, y borres todas. Es posible hayas actualizado el software de Storable mientras que en las sesiones queden algunas con formato de la versión anterior.
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: CGI::Application y CGI::Session

Notapor noa86 » 2011-04-14 17:38 @776

¿Cómo puedo configurar mi CGI::Application, para poder utilizar la misma sesión abierta en el CGI, a través de CGI::Session, las cuales se me almacenan en una tabla de una base de datos MySQL? ¿Y que si la sesión se cierra desde el cgi, ya no se pueda acceder al CGI::Application?
noa86
Perlero nuevo
Perlero nuevo
 
Mensajes: 93
Registrado: 2010-11-15 14:43 @655

Re: CGI::Application y CGI::Session

Notapor explorer » 2011-04-14 19:54 @871

Un momento... si estás usando CGI::Application, no te debería hacer falta cargar CGI ni CGI::Session.

Es decir:
  • no te hace falta cargar CGI porque CGI::Application ya lo carga por defecto. Puedes acceder al objeto CGI por medio del método query(), tal como explica en el manual:
    query()
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
        my $q = $webapp->query();
        my $remote_user = $q->remote_user();
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

    Este método retorna el objeto query de CGI.pm que fue creado al crear la instancia de tu módulo de aplicación. Para los detalles en el uso de este objeto query, referirse a CGI. CGI::Application se soporta sobre el módulo CGI. Generalmente hablando, querrá hacerse familiar con CGI.pm, porque usará el objeto query siempre que quiera interactuar con datos provenientes de los formularios.

    Cuando se llama al método new(), un objeto CGI query se crea automáticamente. Si, por alguna razón, quiere usar su propio objeto CGI query, el método new() soporta la opción de pasárselo usando el atributo QUERY.

    Hay unas raras situaciones donde quizás quiera usar su propio objeto query después de haber construido su módulo de aplicación. En este caso puede pasárselo a query() así:

    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
        $webapp->query($new_query_object);
        my $q = $webapp->query(); # now uses $new_query_object
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


    Recientemente, hice una aplicación con CGI::Application. En situaciones normales, solo necesitas llamar a query() para obtener acceso al objeto CGI.pm. Pero... en este caso había una diferencia...

    CGI::Application usa el método cgiapp_get_query() para obtener el objeto CGI.pm. El problema es que la forma de obtenerlo es muy básica:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
    1. sub cgiapp_get_query {
    2.         my $self = shift;
    3.  
    4.         # Include CGI.pm and related modules
    5.         require CGI;
    6.  
    7.         # Get the query object
    8.         my $q = CGI->new();
    9.  
    10.         return $q;
    11. }
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
    Como ves, lo único que hace es cargar el módulo CGI y crear un objeto con él. Y con él podemos llamar a las funciones típicas del módulo CGI, incluidas las de generación de código HTML.

    El problema es que yo necesitaba que ese objeto CGI tuviera, además, puesta la opción -newstyle_urls. En un programa cgi normal, hubiera puesto:
    use CGI qw(:html2 :html3 :html4 :form -newstyle_urls);
    pero, como ves en el código anterior, eso no es lo que ocurre. Así que no queda más remedio que darle a CGI::Application nuestro propio objeto CGI.

    Hay varias formas de hacerlo:
    1.- sobreescribiendo el método cgiapp_get_query()
    2.- crear un objeto CGI y pasárselo a CGI::Application.
    3.- (no comentado en el manual). Haces un 'use CGI (resto de opciones)' dentro del package de tu aplicación, antes del 'use base "CGI::Application";'. Esto, tiene el efecto de cargar el módulo CGI en memoria, pero con nuestras opciones. Cuando CGI::Application lo requiera, al crearse el objeto de nuestra aplicación (que será del tipo CGI::Application), llamará al método query(), y como el módulo CGI ya estará cargado, la línea 'require CGI' no tendrá efecto, por lo que, luego, con la línea 'my $q = CGI->new();' se estará creando un objeto CGI pero con nuestras opciones.
    4.- (seguro que hay alguna más)

    La verdad es que es un poco enrevesado, y casi es mejor usar alguna de las dos primeras opciones.

    Pero... repito: en la mayor parte de las ocasiones, no vas a necesitar crear un objeto CGI, sino que, simplemente, solo tendrás que llamar al método query() para tener acceso a ese objeto.
  • si vas a usar sesiones, es mejor usar el complemento CGI::Application::Plugin::Session. Este módulo carga CGI::Session por ti. Lo único que tienes que hacer es:
    1.- en cgiapp_init() (por ejemplo), indicas las opciones en las que van a trabajar las sesiones, es decir, si son en ficheros de texto, o en base de datos. Yo, por ejemplo, para guardar las sesiones en disco:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
        $self->session_config(
            CGI_SESSION_OPTIONS     => [ 'driver:File', $query, {Directory => "$DIRECTORIO_WEB/sesiones"} ],
            DEFAULT_EXPIRY          => '+90d',
            COOKIE_PARAMS           => { -expires => '+90d' },
            SEND_COOKIE             => 1,
        );
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

    session_config() es un método de CGI::Application::Plugin::Session, donde indicamos las opciones que queremos que tengan las sesiones. En este ejemplo, uso el 'driver:File', para guardar las sesiones en disco.

    2.- a partir de ese momento, dentro del programa solo necesito referirme al método session() para acceder al objeto CGI::Session creado por este complemento.

Para controlar el tema de sesiones caducadas, puede ser por el tiempo de expiración, o porque el usuario ha decidido hacer un logout.

En caso de logout, te vale con hacer algo como esto (en el RunMode del logout, por ejemplo):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$self->session_recreate;                      # creamos una nueva CGI::Session
$session = $self->session;                    # la obtenemos
$session->param(email => '', usuario => '');  # y asignamos unos valores vacíos
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
De esta manera, rompes el vínculo con la sesión que mantenía el usuario. Al hacer el session_recreate(), CGI::Application transmite una nueva cookie, que ya no tiene nada que ver con la anterior. Y como pones algunos parámetros con valores vacíos, tu programa, en la siguiente ocasión que es ejecutado, sabe que es una sesión nueva (o un nuevo usuario).

En el caso de expiración por tiempo, no hay que hacer nada:
* el navegador web del usuario, dejará de enviar las galletas (cookies) caducadas
* si recibimos una cookie para una sesión que ha caducado (mirar el atributo DEFAULT_EXPIRY de más arriba), tampoco importa porque CGI::Application::Plugin::Session creará una sesión nueva en la primera ocasión en la que llamemos al método session().

Lo más sencillo para controlar el acceso del usuario: ver si un determinado parámetro existe en la sesión actual. Si, por ejemplo, no existe O está vacío el parámetro 'registrado' (sacado de $self->session->param('registrado')) entonces sabemos que el usuario no se ha identificado, por lo que le sacaremos en la página un contenido distinto que si sí lo estuviera.
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: CGI::Application y CGI::Session

Notapor noa86 » 2011-04-15 05:01 @251

Pero mi problema es que tengo un archivo Perl en el que uso CGI::Session, y cargo ahí las nuevas sesiones.

¿En CGI::Application puedo usar CGI::Application::Plugin::Session para cargar la session creada en el archivo Perl anterior? ¿Y si no se ha iniciado sesión en ese archivo se redireccione?

El archivo Perl es main.Perl. Y luego está app.pl y app.pm, donde estoy configurando elcgi::application, Pero si no ha iniciado session en main.Perl que tengo CGI::Session quiero que no pueda entrar en app.pl.

No sé si me he explicado bien...
noa86
Perlero nuevo
Perlero nuevo
 
Mensajes: 93
Registrado: 2010-11-15 14:43 @655

Re: CGI::Application y CGI::Session

Notapor explorer » 2011-04-15 18:11 @799

noa86 escribiste:¿En CGI::Application puedo usar CGI::Application::Plugin::Session para cargar la session creada en el archivo Perl anterior?
Sí que se puede usar. Son los mismos ficheros, con el mismo formato. Por una razón: porque CGI::Application::Plugin::Session usa el módulo CGI::Session (solo tienes que ver el código fuente del primero).

noa86 escribiste:¿Y si no se ha iniciado sesión en ese archivo se redireccione?
Eso es otra cosa: cuando arranque el programa, debes comprobar si la sesión está vacía o expirada. O si no está vacía ni expirada, ver si algún parámetro de la sesión que indica que el usuario ha iniciado la sesión te dice en qué estado está la sesión, y así le presentas al usuario una página u otra.

noa86 escribiste:El archivo Perl es main.Perl. Y luego está app.pl y app.pm, donde estoy configurando el cgi::application, Pero si no ha iniciado session en main.Perl que tengo CGI::Session quiero que no pueda entrar en app.pl.

No sé si me he explicado bien...
Pues no... ¿cómo sabes tú que se ha iniciado una sesión?

Lo normal es que el usuario se identifique en el formulario de entrada. Nosotros recibimos una petición a nuestro CGI proveniente de ese formulario. Verificamos al usuario. Si el usuario es legal, actualizamos un parámetro de la session para indicar que sí, que a partir de ese momento, toda conexión que llegue desde esa máquina, identificada por esa sesión, es de un usuario identificado.

Si el usuario pulsa en Desconexión, o pasa el tiempo de expiración de la sesión, nuestra aplicación verá, al principio, que está expirada, por lo que creará una nueva. Y al ser nueva, el parámetro que indica que el usuario está identificado, está vacío.

Como ya he comentado antes, esto está en el ejemplo MEMBERS AREA del CGI::Session::CookBook.
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


Volver a Básico

¿Quién está conectado?

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