Perl CGI从不同的请求获取参数到当前URL

时间:2011-11-23 18:48:12

标签: perl apache cgi mod-perl

这很奇怪。 :)

我有一个在Apache 1.3下运行的脚本,其中包含mod_perl的Apache :: PerlRun选项。它使用标准的CGI.pm模块。它是繁忙服务器上的定期访问脚本,可通过https访问。

网址通常类似于......

  

/script.pl?action=edit&id=47049

然后以通常的方式将其带入Perl ......

my $action = $cgi->param("action");
my $id = $cgi->param("id");

这已成功运作了几年。但是,我们本周开始从访问此脚本并获取空白页面的客户那里获得支持请求。我们已经有了如下所示的行,将当前的URL放入我们用于报告页面问题的表单中...

$cgi->url(-query => 1);

当我们查看页面的来源时,该命令的结果是相同的URL,但是查询字符串完全不同。

  

/script.pl?action=login&user=foo&password=bar

我们认为是来自我们系统其他地方完全不同的脚本的查询字符串。

听起来很疯狂,似乎当用户使用查询字符串访问URL时,脚本看到的查询字符串是来自另一个脚本上的先前请求的字符串。当然,脚本无法处理该操作并且不输出任何内容。

我们运行了一些自动化测试脚本来查看这种情况发生的频率,而且并非每次都有。为了给混合增加一些额外的困惑,在Apache重新启动之后,问题似乎最初完全消失,但后来又回来了。所以无论是什么导致它都会因为重新启动而得到缓解,但是我们无法看到Apache如何从一个用户那里获取请求并将其与另一个用户混合起来。

1 个答案:

答案 0 :(得分:2)

看起来,它是Apache 1.3,mod_perl 1.31,CGI.pm和Apache :: GTopLimit的有趣组合。

去年5月针对CGI.pm记录了一个错误:RT #57184

其中也引用了CGI.pm params not being cleared?

CGI.pm注册一个清理处理程序,以清理它的所有缓存....(第360行)

$r->register_cleanup(\&CGI::_reset_globals);

Apache::GTopLimit(与错误报告中提及的Apache::SizeLimit一样)也有这样的处理程序:

$r->post_connection(\&exit_if_too_big) if $r->is_main;

在pre mod_perl 1.31中,post_connection和register_cleanup似乎推入堆栈,而在1.31中,似乎GTopLimit一个就是CGI.pm条目。因此,如果您的GTopLimit函数因为Apache进程变大而触发,则CGI.pm将不会被清除,并且在下次使用时将其打开以返回相同的参数。

解决方案似乎是将CGI.pm的第360行更改为;

$r->push_handlers( 'PerlCleanupHandler', \&CGI::_reset_globals);

明确地将处理程序推送到列表中。

我们重新启动Apache暂时解决了这个问题,因为它减少了所有进程的大小,并且没有理由让GTopLimit解雇。

我们假设它在过去几周内出现了,因为我们通过新的开发增加了Apache进程的大小,其中包括以前没有的东西。

到目前为止,所有测试都指出这是问题所在,所以手指越过了它!