2015-10-20 108 views
0

我對Perl完全陌生。我已經用C#編寫了一個運行在Windows機器上的Web服務,並使用SOAP :: Lite從Linux機器上的Perl腳本調用它。我的代碼使用http://處理程序正常工作。現在我試圖讓它與https://SOAP :: Lite連接到SSL服務器

工作代碼爲:

use SOAP::Lite; 
    use POSIX; 

    #Tell Perl to trust the testserver's cert 
    #$ENV{HTTPS_CA_DIR} = '/usr/local/share/ca-certificates'; 
    $ENV{HTTPS_CA_FILE} = '/home/myusername/TestServer_CA_Cert.cer'; 
    #$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; 


    my $uri = 'http://Automation/'; 
    my $proxy = 'https://TestServer/ToolsAutomation/AutomationInterface.asmx'; 
    my $method = SOAP::Data->name('SubmitAutomationJob')->attr({xmlns => $uri}); 

    #-Code that sets us @params deleted for readability- 

    my $myServer = SOAP::Lite 
     -> on_action(sub {join '', $uri, $_[1]}) 
     -> proxy($proxy) 
    #  -> proxy($proxy, ssl_opts => [ SSL_verify_mode => 0 ]) 
    #  -> proxy($proxy, ssl_opts => [SSL_ca_file => $ServerCACert]) 
      ; 

    my $myCALL = $myServer #This is line 36 in the original script 
       -> call($method => @params); 

    print 'Result: ' . $myCALL->result; 

當我運行作爲發佈的代碼,我得到錯誤「500無法連接到TESTSERVER:443在行36.」服務器端的網絡跟蹤顯示客戶端發送SYN,服務器發送SYN/ACK,客戶端發送ACK,然後客戶端立即發送FIN/ACK。

我已經嘗試了各種各樣的東西來得到這個工作。我曾嘗試:

  • 取消註釋行#$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;結果爲「500無法連接到TESTSERVER:443(證書驗證失敗)網絡跟蹤顯示HTTPS談判的至少部分工作
  • 取消註釋。線proxy($proxy, ssl_opts => [ SSL_verify_mode => 0 ])作品,當然這並不驗證服務器的身份。
  • 取消註釋行-> proxy($proxy, ssl_opts => [SSL_ca_file => $ServerCACert])還提供了一個「證書驗證失敗」的錯誤。
  • 路徑更改爲$ENV{HTTPS_CA_FILE}給出了一個錯誤「SSL_ca_file /家/名爲myUsername /TestServer_CA_cert.ceeer不存在「在第36行。我認爲這是一個好兆頭;代碼是找到我告訴它用於服務器認證的證書。
  • $ENV{HTTPS_CA_DIR}$ENV{HTTPS_CA_FILE}行取消註釋會提示錯誤「應只給出SSL_ca_path或SSL_ca_file」。

我已經將我的CA證書導入到Linux機器的Firefox中,併成功瀏覽到我的testserver而沒有收到SSL警告,然後從Firefox中刪除證書並瀏覽並收到SSL警告,有理由相信我擁有的證書文件很好。

有沒有人有任何想法如何解決這段代碼?我應該檢查CA證書本身的某些屬性嗎?我覺得令人費解的是,Firefox沒有任何問題信任SSL證書使用此CA證書籤名的服務器,但我無法說服Perl也這樣做。

任何反饋意見。請記住:我是絕對的Perl n00b。在我搜索如何從Perl調用Web服務之前,我唯一認爲我知道Perl的是「Larry Wall」。

謝謝!

UPDATE:

在斯特芬烏爾裏希的請求的下方,我跑以下:

perl -MIO::Socket::SSL=debug4 program.pl 

我接收到的輸出是:

[email protected]:~$ perl -MIO::Socket::SSL=debug4 ./program.pl 
DEBUG: .../IO/Socket/SSL.pm:402: socket not yet connected 
DEBUG: .../IO/Socket/SSL.pm:404: socket connected 
DEBUG: .../IO/Socket/SSL.pm:422: ssl handshake not started 
DEBUG: .../IO/Socket/SSL.pm:1388: SSL structure creation failed 
+0

類似的問題,可能有所幫助:http://stackoverflow.com/questions/14839098/perl-cannot-access-web-service-with-ssl – Narthring

回答

0

當我運行的代碼作爲發佈,我得到錯誤「500無法連接到測試服務器:443在36線」。服務器端的網絡跟蹤顯示客戶端發送SYN,服務器發送SYN/ACK,客戶端發送ACK,然後客戶端立即發送FIN/ACK。

如果這真的像你描述它那麼沒有數據交換,這意味着客戶端甚至不會嘗試執行SSL握手。這意味着,可能是你叫的方式是錯誤的:

#  -> proxy($proxy, ssl_opts => [ SSL_verify_mode => 0 ]) 
#  -> proxy($proxy, ssl_opts => [SSL_ca_file => $ServerCACert]) 

我敢肯定,ssl_opts不需要一個數組([...]),但是哈希({...})。

編輯: 它看起來像你需要一個數組,而不是一個散列,因爲ssl_opts以一種特殊的方式通過SOAP ::精簡版,即它們不直接給LWP ::用戶代理的構造函數的文檔處理會意味着。我有filed a bug about it

DEBUG: .../IO/Socket/SSL.pm:1388: SSL structure creation failed 

根據我從你得到了我可以重現該問題,但前提是給定的CA文件已損壞的代碼。我希望這是你的情況。請注意,該文件必須如下所示:

-----BEGIN CERTIFICATE----- 
MIIDKDCCApGgAwIBAgIJAOetiwdVihcnMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNV 
.... more base64 encoded stuff ... 
M0LUhtV8z6OcURDEfnQBsgLCPODc9Mg4FEViDGVaZ1i233ZeAlLzXSZeXL8= 
-----END CERTIFICATE----- 
+0

你是對的;在那個測試用例中,握手不會被嘗試。在其他測試案例中,握手確實足以讓客戶端返回「證書驗證失敗」錯誤。另外,當我使用您引用的第一條註釋行時,客戶端確實成功連接到服務器,但當然不會執行證書驗證檢查。 – Nevo

+0

@Nevo:你能否用正確的SSL_ca_file和'perl -MIO :: Socket :: SSL = debug4 program.pl'調用你的代碼,並將調試輸出添加到你的問題中? –

+0

Steffen,請參閱原帖的更新。謝謝你。我正在研究調試命令的輸出。 – Nevo

0

Steffen提供了正確的解決方案。當我最初從Windows CA導出CA證書時,我以「DER編碼二進制X.509」格式導出它。這是失敗的。

我以「Base-64 encoded X.509」格式重新導出證書,並在我的Perl腳本中使用該證書,現在事情正常運行。