5

I am very new to Perl and i am learning on the fly while i try to automate some projects for work. So far its has been a lot of fun.

I am working on generating a report for a customer. I can get this report from a web page i can access. First i will need to fill a form with my user name, password and choose a server from a drop down list, and log in. Second i need to click a link for the report section. Third a need to fill a form to create the report.

Here is what i wrote so far:

my $mech = WWW::Mechanize->new();
my $url = 'http://X.X.X.X/Console/login/login.aspx';

$mech->get( $url );

$mech->submit_form(
     form_number => 1,
     fields      =>{
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtUser'  => 'someone',
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtPW'    => '12345',
        'ctl00$ctl00$cphVeriCentre$cphLogin$ddlServers'  => 'Live',
     button => 'Sign-In'
   },   
);
die unless ($mech->success);

$mech->dump_forms();

I dont understand why, but, after this i look at the what dump outputs and i see the code for the first login page, while i belive i should have reached the next page after my successful login.

Could there be something with a cookie that can effect me and the login attempt?

Anythings else i am doing wrong?

Appreciate you help, Yaniv

4

5 回答 5

6

这是事实发生几个月后,但我根据我提出的类似问题解决了同样的问题。请参阅是否可以从客户端自动回发?了解更多信息。

我使用了 Python 的 Mechanize 或 Perl,但同样的原则也适用。

总结一下我之前的回答:

ASP.NET页面在表单中需要一个名为__EVENTTARGET的隐藏参数,正常使用mechanize时是不存在的。

当普通用户访问时,这些页面上有一个 __doPostBack('foo') 函数,该函数通过每个链接上的 javascript onclick 事件为 __EVENTTARGET 提供相关值,但由于 mechanize 不使用 javascript,因此您需要自己设置这些值。

下面是python解决方案,但将其适应perl应该不会太难。

def add_event_target(form, target):
    #Creates a new __EVENTTARGET control and adds the value specified
    #.NET doesn't generate this in mechanize for some reason -- suspect maybe is 
    #normally generated by javascript or some useragent thing?
    form.new_control('hidden','__EVENTTARGET',attrs = dict(name='__EVENTTARGET'))
    form.set_all_readonly(False)
    form["__EVENTTARGET"] = target
于 2009-08-17T20:07:06.173 回答
2

你只能机械化你知道的东西。在您编写更多代码之前,我建议您使用 Firebug 之类的工具,并在手动执行此操作时检查浏览器中发生的情况。

当然,可能会使用 cookie。或者您可能忘记了隐藏的表单参数?只有你能说出来。

编辑:

  • WWW::Mechanize 应该在没有任何进一步干预的情况下处理 cookie。
  • 您应该始终检查您调用的方法是否成功。第一个 get() 有效吗?
  • 查看服务器日志以查看实际请求的内容以及作为响应发送的 HTTP 状态代码可能很有用。
于 2009-06-09T09:38:53.520 回答
2

如果您使用的是 Windows,请使用Fiddler查看手动执行此过程时发送的数据,然后使用 Fiddler 将其与脚本执行时捕获的数据进行比较。

根据我的经验,在检查表单帖子时,像Fiddler这样的 Web 调试代理比 Firebug 更有用。

于 2012-05-10T11:47:34.330 回答
1

我发现在Wireshark使用WWW::Mechanize. 它将通过以下几种方式帮助您:

  1. 让您意识到您的 HTTP 请求是否成功。
  2. 查看 HTTP 级别的失败原因。
  3. 跟踪您传递给服务器的确切数据并查看您收到的内容。

只需为网络流量设置一个 HTTP 过滤器并启动您的 Perl 脚本。

于 2013-03-19T03:30:39.300 回答
0

aspx 页面的非常简短的要点是,它们将所有本地会话信息保存在几个以通用 aspxform 为前缀的变量中。通常这是一个顶级表单,所有表单元素都将成为其中的一部分,但我想这可能会因实现而异。

对于我正在处理的特定实现,我需要担心其中的 2 个状态变量,特别是:

__VIEWSTATE
__EVENTVALIDATION.

您的目标是确保将这些变量提交到您提交的表单中,因为它们可能是我上面提到的主表单 aspxform 的一部分,并且您可能提交的表单与此不同。

当浏览器加载一个 aspx 页面时,一段 javascript 在 asp 服务器/客户端交互中传递此会话信息,但当然我们没有 perl 机械化那么奢侈,因此您需要自己手动发布这些信息,方法是添加使用 mechanize 将元素转换为当前形式。

在我刚刚解决的情况下,我基本上是这样做的:

my $browser = WWW::Mechanize->new( );

# fetch the login page to get the initial session variables
my $login_page = 'http://www.example.com/login.aspx';
$response = $browser->get( $login_page);

# very short way to find the fields so you can add them to your post
$viewstate = ($browser->find_all_inputs( type => 'hidden', name => '__VIEWSTATE' ))[0]->value;
$validation = ($browser->find_all_inputs( type => 'hidden', name => '__EVENTVALIDATION' ))[0]->value;

# post back the formdata you need along with the session variables
$browser->post( $login_page, [ username => 'user', password => 'password, __VIEWSTATE => $viewstate, __EVENTVALIDATION => $validation ]);

# finally get back the content and make sure it looks right
print $response->content();
于 2012-05-10T01:48:40.390 回答