2014-03-27 57 views
3

我正在嘗試使用apache http client連接SOAP Web服務。它是安全的(由https標識)。我已經添加了密鑰庫文件的代碼。 下面是代碼:在測試SOAP Web服務時獲取SSLHandshakeException

CloseableHttpClient httpclient = null; 
try { 
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    FileInputStream instream = new FileInputStream(new File("C:\\SOAP\\qa.keystore")); 
    try { 
     trustStore.load(instream, "test1234".toCharArray()); 
    } 
    catch(Exception e){ 
     e.printStackTrace(); 
    } 
    finally { 
     instream.close(); 
    } 

    SSLContext sslcontext = SSLContexts.custom() 
      .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) 
      .build(); 

    httpclient = HttpClients.custom() 
      .setSslcontext(sslcontext) 
      .build(); 

    HttpPost httppost = new HttpPost("https://dev env hostname:7443/wsx/services/reiveFile_WS_VT_SECURED_INBOUND"); 
    FileBody bin = new FileBody(new File("C:\\Payment Check8jan3.dat")); 
    StringBody fileName = new StringBody("Payment Check8jan3.dat", ContentType.TEXT_PLAIN); 
    StringBody fileType = new StringBody("111", ContentType.TEXT_PLAIN); 
    StringBody messageId = new StringBody("3454", ContentType.TEXT_PLAIN); 
    StringBody senderId = new StringBody("ekrjekrj", ContentType.TEXT_PLAIN); 
    StringBody checksum = new StringBody("b2ee8af554ab6933085d341b71765bc8", ContentType.TEXT_PLAIN); 
    StringBody timestamp = new StringBody("3434", ContentType.TEXT_PLAIN); 
    StringBody transportServiceVersion = new StringBody("4343", ContentType.TEXT_PLAIN); 


    HttpEntity reqEntity = MultipartEntityBuilder.create() 
      .addPart("FileName", fileName) 
      .addPart("FileType", fileType) 
      .addPart("messageId", messageId) 
      .addPart("senderId", senderId) 
      .addPart("checksum", checksum) 
      .addPart("timestamp", timestamp) 
      .addPart("transportServiceVersion", transportServiceVersion) 
      .addPart("payload", bin) 
      .build(); 

    httppost.setEntity(reqEntity); 

    System.out.println("executing request " + httppost.getRequestLine()); 

    CloseableHttpResponse response = httpclient.execute(httppost); 
    try { 
     System.out.println("----------------------------------------"); 
     System.out.println(response.getStatusLine()); 
     HttpEntity resEntity = response.getEntity(); 
     if (resEntity != null) { 
      System.out.println("Response content length: " + resEntity.getContentLength()); 
     } 
     EntityUtils.consume(resEntity); 
    } finally { 
     response.close(); 
    } 
} finally { 
    httpclient.close(); 
} 

我收到以下異常:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275) 
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254) 
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:117) 
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314) 
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363) 
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219) 
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195) 
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86) 
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) 
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) 
    at Test.test(Test.java:113) 
    at Test.main(Test.java:229) 
Caused by: java.io.EOFException: SSL peer shut down incorrectly 
    at sun.security.ssl.InputRecord.read(Unknown Source) 
    ... 18 more 

編輯: 作爲答案的一個建議,我導入證書到cacerts中也文件。但仍然得到相同的例外。 請推薦。

+0

您是否嘗試過運行命令行openssl來查看服務器正在呈現的內容? openssl s_client -debug -showcerts -connect「dev env主機名:7443」 –

回答

0

嘗試將證書導入cacerts文件或創建一個新文件,同樣指向託管/使用Web服務的服務器。

如果將完整的證書鏈導入到truststore中,也請檢查是否正確。 可以通過程序或通過導入cacerts來實現。 更好的方式來導入trusstore,如果導入正確,還檢查公鑰和私鑰。

+0

請問您能解釋一下嗎?或讓我提供我可以遵循的任何鏈接 – Anand

+0

您能否請您解釋一下您的架構,使用的服務器,託管和使用的Web服務以及您如何測試 –

+0

正如您所建議的那樣,我還將證書導入「cacerts」文件,但仍然同樣的例外。我通過提供密鑰庫文件來測試使用Soap UI的服務,但通過Java調用不起作用。您是指「如果完整的證書鏈導入到信任庫中,則檢查是否正確」。如何檢查? – Anand

0

這只是一個猜測,但鑑於SSL握手在初始階段失敗,我會懷疑協議版本不兼容。嘗試強制使用較舊的協議版本,例如SSLv3SSLv2,並查看是否有任何區別。

SSLContext sslcontext = SSLContexts.custom() 
    .loadTrustMaterial(trustStore) 
    .build(); 
SSLConnectionSocketFactory sslcsf = new SSLConnectionSocketFactory(
    sslcontext, new String[] {"SSLv3"}, null, null); 
CloseableHttpClient client = HttpClients.custom() 
    .setSSLSocketFactory(sslcsf) 
    .build(); 

通常,在處理任何類型的SSL問題時,SSL初始握手的調試日誌通常足以查明問題的原因。有關詳細信息,請參閱this troubleshooting guide