测试SOAP Web服务时出现SSLHandshakeException异常

3

我正在尝试使用apache http client连接一个SOAP web服务。它是一个安全的服务(通过https进行标识)。我已经添加了keystore文件的代码。

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文件中。但仍然出现相同的异常。 请建议解决方案。


你尝试过运行命令行openssl来查看服务器呈现的内容吗?openssl s_client -debug -showcerts -connect "dev env hostname:7443" - Peter G
2个回答

0

尝试将证书导入到cacerts文件中或创建一个新的文件,同时将其指向您托管/消耗Web服务的服务器。

还要仔细检查是否完整地将证书链导入到truststore中。 可以通过编程或导入到cacerts中实现相同的功能。 更好的方法是导入到trusstore中,还要检查公钥和私钥是否已正确导入。


请问您能否详细解释一下?或者提供一个链接让我可以跟进。 - Anand
请问您能否解释一下您的架构、使用的服务器、托管和消费的 Web 服务,以及您如何进行测试? - Ankur Singhal
正如您建议的那样,我已将证书导入到“cacerts”文件中,但仍然出现相同的异常。我已使用Soap UI测试了该服务,提供了密钥库文件,但通过Java调用不起作用。您所说的“仔细检查是否完全导入了证书链”,是什么意思?如何检查呢? - Anand
您可以在记事本中打开“cacerts”文件,通过引用您在导入过程中提供的别名名称来查看证书。我建议您参考“Keytool”了解所有相关命令,它非常有用。 还要检查所提供给您的证书,必须为p7b格式,密钥为der格式或pk7。可能需要将其转换为适当的格式以导入到“cacerts”中。此外,当您通过服务器运行时,服务器需要将其发送给另一个服务器以进行握手。 - Ankur Singhal
越多阅读,就会越清楚。我个人也有关于SSL的经验,你可以看看我在SSL方面提出的问题,我也曾经遇到过很多困难,但最终还是成功了。看看我的问题,或许能更好地帮助你。 - Ankur Singhal

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初始握手的调试日志通常足以确定问题的原因。有关详细信息,请参见此故障排除指南

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接