2012-10-02 91 views
8

我將一個應用程序從PHP/cURL移植到Perl和LWP :: UserAgent。我需要對Web服務器執行POST請求並提供客戶端證書和密鑰文件。我試圖複製的PHP代碼是這樣的:使用帶有SSL和客戶端證書的LWP

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSLCERT, "/path/to/certificate.pem"); 
curl_setopt($ch, CURLOPT_SSLKEY, "/path/to/private.key"); 
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, "secretpassword"); 

這是我的Perl代碼:

my $ua = LWP::UserAgent->new(); 
$ua->ssl_opts(
    SSL_verify_mode => 0, 
    SSL_cert_file => '/path/to/certificate.pem', 
    SSL_key_file => "/path/to/private.key", 
    SSL_passwd_cb => sub { return "secretpassword"; } 
); 

的PHP代碼成功地連接到服務器,但Perl代碼失敗:

SSL讀取錯誤錯誤:14094410:SSL例程:SSL3_READ_BYTES:sslv3警報握手失敗

我找不出我缺少的東西。

+0

'private.key'(PHP)和'private.pem'(Perl)是錯字還是移植的一部分? – amon

+2

將多個參數傳遞給[ssl_opts](https://metacpan.org/module/LWP::UserAgent#ATTRIBUTES)沒有記錄。爲了安全起見,可以多次調用ssl_opts或將它們傳遞給構造函數。我認爲它正常工作,但更安全。您也可以[將其報告爲缺陷/缺失功能](https://rt.cpan.org/Public/Bug/Report.html?Queue=libwww-perl)。 – Schwern

+0

當我隱藏我的代碼時,這只是一個錯字。它應該是私有的。感謝您的注意,但這不是問題。仍然需要幫助! :) – kent

回答

2
sub send_command(){ 
     my $command = shift; 
     my $parser = XML::LibXML->new('1.0','utf-8'); 

     print color ("on_yellow"), "SEND: ", $command, color ("reset"), "\n"; 

     # Create a request 
     my $req = HTTP::Request->new(GET => $Gateway.$command); 

     # Pass request to the user agent and get a response back 
     my $res; 
     eval { 
       my $ua; 
       local $SIG{'__DIE__'}; 
       $ua = LWP::UserAgent->new(); # или 
       $ua->ssl_opts(#$key => $value 
        SSL_version   => 'SSLv3', 
        SSL_ca_file   => '/ca.pem', 
        #SSL_passwd_cb  => sub { return "xxxxx\n"; }, 
        SSL_cert_file  => '/test_test_cert.pem', 
        SSL_key_file  => '/test_privkey_nopassword.pem', 
       ); # ssl_opts => { verify_hostname => 0 } 
       $ua->agent("xxxxxx xxxx_tester.pl/0.1 "); 
       $res = $ua->request($req); 

     }; 
     warn [email protected] if [email protected]; 
     # Check the outcome of the response 
     if ($res->is_success) { 
       open xxxLOG, ">> $dir/XXXX_tester.log"; 
       my $without_lf = $res->content; 
       $without_lf =~ s/(\r|\n)//gm; 
       print PAYLOG $without_lf,"\n"; 
       close PAYLOG; 
     } 
     else { 
       return $res->status_line; 
     }  
     print color ("on_blue"), "RESPONSE: ", color ("reset"), respcode_color($res->content), color ("reset"),"\n\n"; 
     return $res->content; 
} 
3

從上面的emazep的答案解決了我的問題。我使用UPS的示例Perl代碼通過XML連接到他們的Rate服務。從我的測試中可以看出,LWP :: UserAgent在任何時候都可以被調用,而不需要直接控制的參數,如果你使用其他模塊來爲你調用LWP,這會很方便。只需使用Net :: SSL(除了任何包已經使用LWP),並設置一些環境變量:

... 
use Net::SSL; 
$ENV{HTTPS_VERSION} = 3; 
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; 
my $browser = LWP::UserAgent->new(); 
... 

這就是它!您甚至不需要使用$ ENV {PERL_LWP_SSL_CA_FILE}指定服務器根證書的路徑。

1

確實這是一個混亂的位。根據您的設置,LWP :: UserAgent可以使用(至少)兩個SSL模塊中的一個來處理SSL連接。

  • IO ::插座:: SSL
  • 的Net :: SSL

第一個應該是LWP ::用戶代理的較新版本的默認值。可以測試其這些是由在對於每個模塊的終端上運行的標準命令設置:

perl -e 'use <module>;' 

IO ::插座:: SSL需要與ssl_opts如在您的示例的SSL配置。

Net :: SSL需要環境變量中的SSL配置,正如在goddogsrunnings答案中一樣。

我個人屬於第二類,並從Crypt::SSLeay page有很好的靈感。特別是名爲「CLIENT CERTIFICATE SUPPORT」的部分。