开发者

Why does CGI::Session new and load fail ( couldn't thaw() )?

I tried using the CGI::Session Library but for some reason my code won't keep a persistant session ... this is using Perl Moose for OOP, and is using Moose builders to instantiate the _cgi and _sss (session) parameters of a My::Session object...

UPDATED CODE

My::Role::PersistantData

package My::Role::PersistsData;

use Moose::Role;
use namespace::autoclean;
  has '_cgi' => (
           is        => 'rw', 
           isa       => 'Maybe[CGI]', 
           builder   => '_build_cgi'
  );

  has '_sss' => (
           is        => 'rw', 
           isa       => 'Maybe[CGI::Session]',
           builder   => '_build_sss'
  );

My::Session

    package My::Session;

    use Moose;
    use namespace::autoclean;
    with 'My::Role::PersistsData';  

    use CGI;
    use CGI::Session ('-ip_match');
    use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;

    sub start{
      my($self) = @_;
      my $cgi = $self->cgi();
      $self->log("Session Started!");        
    }


    sub cgi{
      my($self) = @_;
      $self->_cgi = $self->_build_cgi() unless $self->_cgi;
      return ($self->_cgi); 
    }


    sub _build_cgi{
      my($self) = @_; 
      my $cgi = CGI->new();

      if(!$cgi){
        #print "mising cgi";          
      }

      return ( $cgi );
    }


    sub _build_sss{
          my($self) = @_;
          my $cgi = $self->cgi(); 

          my $sid = $cgi->cookie("CGISESSID") || $cgi->param('CGISESSID') || undef;

          $self->log("Session ID Initial is: ".($sid?$sid:"undef"));

          my $sss =  CGI::Session->new(undef, $cgi, {Directory=>'tmp'})  or die CGI::Session->errstr;



          my $cookie = $cgi->cookie(CGISESSID => $sss->id() );


          $self->log("Resulting Session ID is: ".$sid." cookie is: ".$cookie);    

          print $cgi->header( -cookie=>$cookie );

          return ( $sss );
    }

main.pl

use Data::Dumper; 
$Data::Dumper::Sortkeys = 1;

use CGI;
use CGI::Carp qw(fatalsToBrowser);
use My::Session;

$| = 1;
$, = " ";
$\ = "\n <br />";

  my $sss = My::Session->new();      
  $sss->start();
  print Dumper($sss);

It's pretty weird because the first time I run this I get an actual CGISESSION ID and I am able to carry it over on a page refresh...

however if I load the page again, suddenly the $sss (session) comes back as undefined, when it should return a new Session object:

 $sss = new CGI::Session("driver:File", $sid, {Directory=>'/tmp'})

for some reason $sss is coming back as undefined, which means it didnt initiate a new Session. A few tweaks to my code revealed this error:

new(): failed: load(): couldn't thaw() data using CGI::Session::Serialize::default:thaw(): couldn't thaw. syntax error at (eval 253) line开发者_如何学编程 2, near &quot;/&gt;&quot; 

I also snooped around in CGI::Session.pm and found where this error was being thrown at, I guess it's not able to parse _DATA or even read it...because of some strange characters... "/>"

CGI::Session.pm

....
    $self->{_DATA} = $self->{_OBJECTS}->{serializer}->thaw($raw_data);
    unless ( defined $self->{_DATA} ) {
        #die $raw_data . "\n";
        return $self->set_error( "load(): couldn't thaw() data using $self->{_OBJECTS}->{serializer} :" .
                                $self->{_OBJECTS}->{serializer}->errstr );
    }

Any idea why this isnt working?


Most likely this is due to a different session cookie being sent (been there, hit that wall with head. HARD).

Please print the session cookie value being used to store the session initially as well as session cookie value supplied by subsequent request.

If they are indeed different, you have 2 options:

  • Investigate why different session cookie is sent by the browser in subsequent requests and fix that issue somehow.

    I was never able to find conclusive answer but my app consisted of a frame with internal <iframe> so I suspect it was due to that.

  • If like me you can't find the root cause, you can also work around this.

    My workaround: explicitly STORING the original session cookie value as a form variable being passed around 100% of your code pieces.

    Then re-initialize session object with correct cookie value before your server side code requests session data.

    Not very secure, annoying, hard to get right. But works. I wouldn't recommend it except as a uber-last-resort hack


Perhaps you could try (or at least look at the code to see how it works) for some stateful webapp module. I have used Continuity, very cool stuff.


For some reason you can't use Data::Dumper or other HTML tags with CGI::Session

Answer found here and here

Removing Dumper and HTML output fixed this problem -- kind of --

updated

Apparently you have to use escapes

 $cgi->escapeHTML ( Dumper($session) );

and that FINALLY resolves this problem.

Perl is a pain!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜