我尝试使用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 "/>"
我还在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 );
}
知道为什么这不起作用吗?
答案 0 :(得分:1)
这很可能是因为发送了一个不同的会话cookie(在那里,用头撞墙.HARD)。
请打印最初用于存储会话的会话cookie值以及后续请求提供的会话cookie值。
如果它们确实不同,您有两种选择:
调查浏览器在后续请求中发送不同会话cookie的原因并以某种方式修复该问题。
我从来没能找到确凿的答案,但我的应用程序包含一个内部<iframe>
的框架,所以我怀疑这是由于那个。
如果像我一样找不到根本原因,你也可以解决这个问题。
我的解决方法:明确地将原始会话cookie值存储为围绕100%代码片段传递的表单变量。
然后在服务器端代码请求会话数据之前,使用正确的cookie值重新初始化会话对象。
不太安全,烦人,很难做对。但是有效。我不推荐它,除非作为最后的度假胜地黑客
答案 1 :(得分:1)
对于某些有状态的webapp模块,也许你可以尝试(或者至少查看代码以了解它是如何工作的)。我使用了Continuity,非常酷的东西。
答案 2 :(得分:1)
由于某些原因,您无法将Data::Dumper
或其他HTML标记用于CGI::Session
删除Dumper和HTML输出修复了这个问题 - 一种 -
<强>更新强>
显然你必须use escapes
$cgi->escapeHTML ( Dumper($session) );
并且最终解决了这个问题。
Perl很痛苦!