好的,这样做的方式是用户通过Web表单进行身份验证并生成会话ID,如下所示:
sub session_open
{
my $sid;
my $user = shift;
if ( open(SEMA, "> ../sema/sess") )
{
flock SEMA, LOCK_EX;
do
{
$sid = generate_session_id();
}
while ( -d "$SDIR/$sid" );
my $sstr = "$user:$ENV{'HTTP_USER_AGENT'}";
write_file('>', "$SDIR/$sid", $sstr);
close SEMA;
}
return $sid;
}
然后会话ID被传递到url中的每个页面,如果会话文件存在并且检出他的用户代理和远程地址,它允许用户继续:
sub check_sid
{
my $sid = shift;
return 0 if $sid =~ /[^\w\d]/;
return 0 if !open(SID, "< $SDIR/$pid");
my ($user, $agent) = split /:/, <SID>, 2;
close SID;
return 0 if $agent ne $ENV{'HTTP_USER_AGENT'}";
return $user;
}
在后台我有一个cron作业,每5分钟运行一个脚本,到期时间为2小时:
foreach (<../session/*>)
{
unlink $_ if -M $_ > 0.08333;
}
我在这里有任何瑕疵和不必要的步骤吗?我想使用user_agent和remote_addr,因为以这种方式插入会话ID会更难。
答案 0 :(得分:9)
您不能假设用户和IP地址之间存在1-1对应关系。多个人可能来自同一个IP地址(代理后面)。可能涉及多个IP地址(用户通过负载平衡或故障转移反向代理)。
任何将IP地址混合到会话方案中的尝试最终会在您最不期望的时候中断,所以不要这样做。
如果您关心会话,请使用SSL。
答案 1 :(得分:4)
使用CGI::Session。另请参阅CGI::Application::Plugin::Session。
session_open
中有竞争条件。
您的会话处理代码是否允许将任何其他会话信息写入会话文件?
在check_sid
,您有my $sid = shift;
,但您尝试打开"$SDIR/$pid"
。
即使您已正确命名要插入到文件名中的变量,也有一个明显的缺陷,即您没有取消会话ID(即,您信任未经检查的输入)。将此与您使用open
的两个参数形式的事实相结合,并且有趣的可能性出现。
在任何情况下,任何人都没有理由编写会话处理代码。这项工作已经为你完成了。不要重新发明轮子。