web-services - 测试 SOAP Web 服务时获取 SSLHandshakeException

标签 web-services ssl soap keystore apache-httpclient-4.x

我正在尝试使用 apache http 客户端 连接 SOAP 网络服务。它是安全的(由 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 文件中。但仍然得到同样的异常(exception)。 请提出建议。

最佳答案

这只是一个猜测,但鉴于 SSL 握手在其初始阶段失败,我怀疑协议(protocol)版本不兼容。尝试强制使用较旧的协议(protocol)版本,例如 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详情

关于web-services - 测试 SOAP Web 服务时获取 SSLHandshakeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22686725/

相关文章:

php - 使用 PHP 生成 XML 签名摘要

android - 自签名证书和 Nativescript Android 应用程序

php - 如何使用带有 PFX 文件和密码的 PHP 连接到 API?

java - 如何使用 Apache CXF 表示没有时区的日期?

ssl - Jetty HttpClient 9 (9.0.0.M5) SSLContextFactory 的 TrustAll 标志不起作用?

google-app-engine - 非默认版本的 appspot.com 子域上的 SSL

php - 与 SecureNet 支付网关集成

c# - SOAP 泛型类型序列化

java - 用于多个应用程序服务器的单个 Java 缓存

java - 无法在 Spring Boot 应用程序中加载应用程序上下文