为什么CGI :: Session new和load失败(无法解冻())?

时间:2011-09-19 14:58:16

标签: perl oop session cgi moose

我尝试使用CGI :: Session Library但由于某种原因我的代码不会保持持久会话...这是使用Perl Moose进行OOP,并使用Moose构建器来实例化_cgi和_sss(会话) My :: Session对象的参数......

更新代码

我::角色:: 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'
  );

我::会话

    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);

这很奇怪,因为我第一次运行这个时会得到一个实际的CGISESSION ID,并且我可以在页面刷新时进行...

然而,如果我再次加载页面,突然$ sss(session)返回为undefined,它应该返回一个新的Session对象:

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

由于某种原因,$ sss以未定义的形式返回,这意味着它没有启动新的会话。对我的代码进行了一些调整后发现了这个错误:

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; 

我还在CGI :: Session.pm中窥探并找到了这个错误被抛出的地方,我猜它无法解析_DATA甚至无法读取它......因为有些奇怪的字符......“/&gt ;”

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 );
    }

知道为什么这不起作用吗?

3 个答案:

答案 0 :(得分:1)

这很可能是因为发送了一个不同的会话cookie(在那里,用头撞墙.HARD)。

请打印最初用于存储会话的会话cookie值以及后续请求提供的会话cookie值。

如果它们确实不同,您有两种选择:

  • 调查浏览器在后续请求中发送不同会话cookie的原因并以某种方式修复该问题。

    我从来没能找到确凿的答案,但我的应用程序包含一个内部<iframe>的框架,所以我怀疑这是由于那个。

  • 如果像我一样找不到根本原因,你也可以解决这个问题。

    我的解决方法:明确地将原始会话cookie值存储为围绕100%代码片段传递的表单变量。

    然后在服务器端代码请求会话数据之前,使用正确的cookie值重新初始化会话对象。

    不太安全,烦人,很难做对。但是有效。我不推荐它,除非作为最后的度假胜地黑客

答案 1 :(得分:1)

对于某些有状态的webapp模块,也许你可以尝试(或者至少查看代码以了解它是如何工作的)。我使用了Continuity,非常酷的东西。

答案 2 :(得分:1)

由于某些原因,您无法将Data::Dumper或其他HTML标记用于CGI::Session

找到答案herehere

删除Dumper和HTML输出修复了这个问题 - 一种 -

<强>更新

显然你必须use escapes

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

并且最终解决了这个问题。

Perl很痛苦!