2

我编写了一个脚本,它通过发送 POST 请求来读取 https 页面的内容,并将其转储到文本文件中。它在 Linux 下运行良好,在安装Shining Light OpenSSL后也可以在我的 Windows 机器上运行。但是客户说他们无法在他们的 Windows 机器上安装任何 exe,并要求提供替代解决方案。

我们这里有其他选择吗?也许一些代理接受 POST 请求,获取 https 内容并将其作为 http 传递?我知道很多一厢情愿的想法,但我只想在这里探索任何可能的选择。

4

1 回答 1

2

使用Win32::IE::Mechanize。如今,所有 Windows 系统都有某些版本的 Internet Explorer(尽管在某些系统上,管理员可能会阻止功能)。

您也可以使用Win32::OLE来“手动”驱动 IE,可以这么说 ;-)

以下代码在我古老的 Windows XP SP3 系统上“工作”。我不确定它是否适用于 Vista 或 Windows 7 UAC。showcgi.pl只是转储$cgi对象的状态。你可以看到下面的输出。

我会在我的博文中更详细地解释发生了什么。

我没有为测试设置 SSL 服务器,但请让我知道脚本在这些修改后是否有效。

#!/usr/bin/env perl

package My::Poster;

use strict; use warnings;

use Const::Fast;
use Try::Tiny;
use Win32::OLE;
use Win32::OLE::Variant;
local $Win32::OLE::Warn = 3;

# http://msdn.microsoft.com/en-us/library/aa768360%28v=vs.85%29.aspx
const my %BrowserNavConstants => (
    navOpenInNewWindow => 0x1,
    navNoHistory => 0x2,
    navNoReadFromCache => 0x4,
    navNoWriteToCache => 0x8,
    navAllowAutosearch => 0x10,
    navBrowserBar => 0x20,
    navHyperlink => 0x40,
    navEnforceRestricted => 0x80,
    navNewWindowsManaged => 0x0100,
    navUntrustedForDownload => 0x0200,
    navTrustedForActiveX => 0x0400,
    navOpenInNewTab => 0x0800,
    navOpenInBackgroundTab => 0x1000,
    navKeepWordWheelText => 0x2000,
    navVirtualTab => 0x4000,
    navBlockRedirectsXDomain => 0x8000,
    navOpenNewForegroundTab => 0x10000,
);

sub new {
    my $class = shift;
    my $self = bless {} => $class;
    $self->init;
    return $self;
}

sub ie {
    my $self = shift;
    my $ie = shift;

    return $self->{ie} unless defined $ie;

    $self->{ie} = $ie;
    return;
}

sub init {
    my $self = shift;

    $self->ie(
        Win32::OLE->new(
            'InternetExplorer.Application',
            sub {
                my $ie = shift;
                try { $ie->Quit if $ie } catch { warn "$_\n" };
            },
        )
    );
    return;
}

sub post {
    my $self = shift;
    my ($url, $data) = @_;

    my $ie = $self->ie;

    my $flags = $BrowserNavConstants{navNoHistory} |
                $BrowserNavConstants{navNoReadFromCache} |
                $BrowserNavConstants{navNoWriteToCache} |
                $BrowserNavConstants{navEnforceRestricted} |
                $BrowserNavConstants{navNewWindowsManaged} |
                $BrowserNavConstants{navUntrustedForDownload} |
                $BrowserNavConstants{navBlockRedirectsXDomain}
    ;

    # $postdata should also be converted to bytes here
    # I don't remember the right way to do it, and it works for ASCII
    # so it should be good enough for now.

    my $postdata = join '&', map join('=', @$_), @$data;

    my $vPostData = Variant(VT_ARRAY|VT_UI1, length $postdata);
    $vPostData->Put($postdata);

    # http://msdn.microsoft.com/en-us/library/aa752133%28v=vs.85%29.aspx
    $ie->Navigate(
        $url,
        $flags,
        '_self',
        $vPostData,
        "Content-Type: application/x-www-form-urlencoded\015\012",
    );

    while ($ie->{ReadyState} != 4) {
        sleep 1;
    }

    return $ie->Document->documentElement->innerHTML;
}

sub DESTROY {
    my $self = shift;
    try { $self->ie->Quit } catch { warn "$_\n" };
    return;
}

package main;

use strict; use warnings;

my $poster = My::Poster->new;

my $html = $poster->post(
    'http://test.localdomain:8080/cgi-bin/showcgi.pl',
    [
        [ thisvar => 'thatvalue', ],
        [ anothervar => 'anothervalue', ],
        [ oh => 'lala', ],
    ],
);

print $html if defined $html;

输出:

$VAR1 = 祝福({
     '.参数' => [
                        'thisvar',
                        '另一个',
                        '哦'
                      ],
     '.crlf' => '
',
     '.globals' => {
                     '调试' => 0,
                     'NO_UNDEF_PARAMS' => 0,
                     'NO_NULL' => 1,
                     '致命' => -1,
                     'USE_PARAM_SEMICOLONS' => 0,
                     'PARAM_UTF8' => 0,
                     'DISABLE_UPLOADS' => 1,
                     'USE_CGI_PM_DEFAULTS' => 0,
                     'NPH' => 0,
                     'POST_MAX' => 102400,
                     'HEADERS_ONCE' => 0
                   },
     '另一个变量' => [
                       '另一个价值'
                     ],
     '哦' => [
               '拉拉'
             ],
     'thisvar' => [
                    '那个值'
                  ],
     '.fieldnames' => {
                        '另一个变量' => 1,
                        '哦' => 1,
                        'thisvar' => 1
                      },
     '.header_printed' => 1
   }, 'CGI::Simple' );
于 2012-04-26T14:34:17.943 回答