2012-10-02 26 views
8

Tôi đang chuyển một ứng dụng từ PHP/cURL sang Perl và LWP :: UserAgent. Tôi cần thực hiện yêu cầu POST đối với máy chủ web và cung cấp chứng chỉ ứng dụng và tệp khóa. Các mã PHP Tôi đang cố gắng để tái tạo là thế này:Sử dụng LWP với SSL và chứng chỉ ứng dụng khách

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"); 

Và đây là mã Perl của tôi:

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"; } 
); 

mã PHP thành công kết nối đến máy chủ nhưng mã Perl không thành công với:

Lỗi lỗi đọc SSL: 14094410: Thường trình SSL: SSL3_READ_BYTES: Cảnh báo lỗi bắt tay sslv3

Tôi không thể hiểu được những gì tôi đang thiếu.

+0

Có phải 'private.key' (PHP) và' private.pem' (Perl) là lỗi đánh máy hoặc một phần của quá trình chuyển? – amon

+2

Chuyển nhiều đối số đến [ssl_opts] (https://metacpan.org/module/LWP::UserAgent#ATTRIBUTES) không được ghi lại. Để an toàn, hãy gọi ssl_opts nhiều lần hoặc chuyển chúng vào hàm tạo. Tôi nghĩ rằng nó sẽ xảy ra để làm việc, nhưng an toàn hơn. Bạn cũng có thể [báo cáo nó như là một lỗi/thiếu tính năng] (https://rt.cpan.org/Public/Bug/Report.html?Queue=libwww-perl). – Schwern

+0

Đó chỉ là lỗi đánh máy khi tôi che khuất mã của mình. Nó phải là private.key cho cả hai. Cảm ơn vì đã chú ý nhưng đó không phải là vấn đề. Vẫn cần trợ giúp! :) – kent

Trả lời

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

Câu trả lời từ emazep đã giải quyết được vấn đề của tôi. Tôi đang sử dụng mã Perl mẫu từ UPS để kết nối với dịch vụ Rate của họ thông qua XML. Từ các bài kiểm tra của tôi, điều này sẽ làm việc bất cứ lúc nào LWP :: UserAgent đang được gọi mà không có đối số mà bạn có thể kiểm soát trực tiếp, điều này giúp bạn sử dụng một số module khác để thực hiện cuộc gọi tới LWP cho bạn. Chỉ cần sử dụng Net :: SSL (ngoài bất kỳ gói nào đã sử dụng LWP) và đặt một vài biến môi trường:

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

Vậy đó! Bạn thậm chí không cần chỉ định đường dẫn đến chứng chỉ gốc của máy chủ của bạn với $ ENV {PERL_LWP_SSL_CA_FILE}.

1

Thực ra đây là một chút lộn xộn. Tùy thuộc vào thiết lập của bạn LWP :: UserAgent có thể sử dụng một trong hai (ít nhất) hai mô đun SSL để xử lý kết nối SSL.

  • IO :: Ổ cắm :: SSL
  • Net :: SSL

Người đầu tiên nên là mặc định cho các phiên bản mới hơn của LWP :: UserAgent. Bạn có thể kiểm tra mà trong số này được cài đặt bằng cách chạy lệnh tiêu chuẩn trong một thiết bị đầu cuối cho mỗi mô-đun:

perl -e 'use <module>;' 

IO :: Socket :: SSL đòi hỏi cấu hình SSL với ssl_opts như trong ví dụ của bạn.

Net :: SSL yêu cầu cấu hình SSL trong biến môi trường như trong câu trả lời goddogsrunnings.

Cá nhân tôi thuộc thể loại thứ hai và có nguồn cảm hứng tốt từ Crypt::SSLeay page. Đặc biệt là phần có tên "H SUP TRỢ CERTIFICATE CERTIFICATE".