为什么我可以使用浏览器登录此表单,但不能通过LWP登录?

时间:2011-04-07 18:51:28

标签: html perl forms post lwp

我试图登录使用此表单的网站,其中包含三个输入进行身份验证。

<form action="/login.html" method="post">
<div class="loginlabel1 aright">ID / Email: </div>
<div class="bsearchfield">
<input type="text" name="profid" class="inputBx" size="15" value="" />
</div>
<div class="clear"></div>
<div class="loginlabel1 aright">Password: </div>
<div class="bsearchfield">
<input type="password" name="password" class="inputBx" size="15" value="" />
</div>
<div class="clear"></div>
<div class="loginbutton1">
<input name="login"type="image" src="images/logi.gif" align="right" border="0" />
</div>
</form>

如果我通过浏览器登录,则成功登录会将我重定向到http://www.example.com/myhome.html

但是以下脚本没有登录并返回相同的login.html页面。我错过了什么?我没有收到任何错误消息。我发布成功吗?

#!/usr/bin/perl -w
use LWP 5.64;
my $browser = LWP::UserAgent->new || die " Failed LWP USER AGENT : $!";
$ENV{HTTP_proxy} = "http://proxy:port";
$browser->env_proxy;
$browser->cookie_jar({});
my @Header    = (
                    'User-Agent'      => 'Mozilla/4.76 [en] (Win98; U)',
                    'Accept'          => 'image/gif, image/x-xbitmap, image/jpeg,image/pjpeg, image/png, */*',
                    'Accept-Charset'  => 'iso-8859-1,*,utf-8',
                    'Accept-Language' => 'en-US',
              );

push @{$browser->requests_redirectable}, 'POST';
$response = $browser->post(
    "http://www.example.com/login.html",
    [
        'profid'   => 'username',
        'password' => 'password'
    ],@Header
);

$response->is_success or die "Failed to post: ", $response->status_line;
print "Successfully posted username and password.\n" if $response->is_fresh;

#printf("%s",$response->content);
printf("%s\n", $response->status_line);
printf("%s",   $response->header("Accept-Ranges"));
printf("%s",   $response->header("Age"));
printf("%s",   $response->header("ETag"));
printf("%s",   $response->header("Location"));
printf("%s",   $response->header("Proxy-Authenticate"));
printf("%s",   $response->header("Retry-After"));
printf("%s",   $response->header("Server"));
printf("%s",   $response->header("Vary"));
printf("%s",   $response->header("WWW-Authenticate"));
delete $ENV{HTTP_PROXY};

4 个答案:

答案 0 :(得分:2)

您的提交按钮是一张图片。单击类型图像的输入时,浏览器会将您单击的像素坐标发送到CGI。在您的表单中,浏览器会发送login.xlogin.y以及profidpassword

BTW,Firebug是调试CGI的绝佳工具。

答案 1 :(得分:1)

有时它们需要正确的accept-encoding和/或referer标头。我还会尝试使用user-agent标头。

答案 2 :(得分:0)

我还建议Firefox使用LiveHTTPHeaders。你打开它,然后提交你的表单,它显示GET或POST到网站的确切内容,包括所有标题,参数和cookie,然后显示来自服务器的所有响应,包括设置cookie,标题和重定向

页面上可能有javascript会创建额外的参数,当您只是查看表单时,您没有看到这些参数,上面描述的图像编码为PacoRG,或者可能要求您先接受cookie并将其发送给登录。

LiveHTTPHeaders还允许您修改标题和“重放” - 这使您可以修改发送到服务器的内容(任何标题,cookie,参数等),以帮助确定服务器登录时实际需要的内容。 p>

此外,我认为默认情况下LWP会自动跟随重定向,因此页面实际上可能会重定向,而您却没有看到它(我相信“simple_request”功能不会跟随重定向。)

在LWP回复中,您可以向后浏览任何重定向:

my $prev_res = $res->previous();
while ( $prev_res ) {
    print $prev_res->status_line . "\n";
    $prev_res = $prev_res->previous();
}

希望这有帮助!

答案 3 :(得分:-1)

您没有提交点击的提交按钮的名称;我怀疑另一端的代码正在检查请求中是否存在该变量,以查看表单是否已提交。

正如PacoRG指出的那样,提交按钮是一个图像;因此,通过在浏览器中单击该按钮进行提交将提交名为“login.x”和“login.y”的字段以及“登录”。

避免此类问题的一个好方法是使用WWW::Mechanize为您完成大量工作,例如:

my $mech = WWW::Mechanize->new;
$mech->get('http://www.example.com/login.html');
$mech-submit_form(
    with_fields => {
        profid => $username,
        password => $password,
    },
);

以上内容将请求登录页面,找到相应的表单并提交。

此外,正如其他人所说,如果您的脚本请求的处理方式与浏览器的请求不同,那么最好的调试方法是获取发送的完整HTTP请求,并查找相关的差异。对于浏览器,您可以使用Firefox的LiveHTTPHeaders或Tamper Data插件等扩展程序,或者使用类似Wireshark的内容来捕获发送的请求。对于脚本,您可以轻松地输出正在发送的请求。

例如,对于使用LWP :: UserAgent或WWW :: Mechanize(其子类LWP :: UserAgent)的脚本,您可以添加:

$mech->add_handler("request_send", sub { shift->dump; return });
$mech->add_handler("response_done", sub { shift->dump; return });

这将转储发送的原始请求以及来自服务器的原始响应。 (将$mech更改为您的LWP :: UserAgent / WWW :: Mechanize对象所在的变量 - 示例中的$browser。)