使用perl CGI.pm获取原始请求正文



我正在使用Apache和Perl CGI构建一个web服务器,该服务器处理发送给它的POST请求。处理部分要求我从请求中获取完全未处理的数据并验证其签名。

客户端发送两种不同类型的POST请求:一种是内容类型设置为application/json,另一种则是内容类型为application/x-www-form-urlencoded

我能够使用cgi->param('POSTDATA')获取application/json数据。但如果我对application/x-www-form-urlencoded数据,即cgi->param('payload')做同样的操作,我会得到数据,但它已经被解码了。我想要原始URL编码格式的数据。即,我想要客户端发送的未处理数据。

我这样做是为了验证Slack发出的请求。

要处理所有情况,包括内容类型multipart/form-data时的情况,请在CGI之前读取(并放回(原始数据。

use strict;
use warnings;
use IO::Handle;
use IO::Scalar;
STDIN->blocking(1); # ensure to read everything
my $cgi_raw = '';
{ 
local $/; 
$cgi_raw = <STDIN>;
my $s;
tie  *STDIN, 'IO::Scalar', $s;
print STDIN $cgi_raw;
tied(*STDIN)->setpos(0);
}
use CGI qw /:standard/;
...

虽然我不确定哪个Perl模块能为您处理这一切,但这里有一个基本的概要。

您的HTML表单应该提交到.cgi文件(或任何其他正确定义的处理程序(。

原始请求类似于以下内容:

POST HTTP/1.1
UserAgent: Mozilla/5.0
Content-Length: 69
Host: 127.0.0.1
(More headers depending on situation and then a single blank line)
(Message Body Containing data)
username=John&password=123J (example)

https://en.wikipedia.org/wiki/List_of_HTTP_header_fields)

将会发生的情况是,这些数据可以通过使用环境变量和stdin的CGI(而不是CGI-perl模块,又名CGI.pm(获得(使用EV传递头假消息,使用stdin传递消息体(。

在Perl中,我认为您需要这样来阅读这些EV:http://perldoc.perl.org/Env.html

这是为了读取stdin:https://perlmaven.com/read-from-stdin

从那时起,您可以根据需要进行处理。

阅读这些内容时要小心。您可能会在其中一个HTTP标头或消息正文中收到格式错误的信息,如100GB的有效数据,这可能会对您造成严重破坏或危险的系统调用等。在将数据传递到其他地方之前,必须进行消毒。

最新更新