SSL通信中的Apache CXFexception:SocketTimeOut

所以这是交易。 我有一个Web服务WSDL,我需要在公司网络之外进行SOAP调用。 Web服务是HTTPS SOAP,需要客户端证书。 我用wsdl2java用Java生成了客户端代码,事情看起来很顺利。

我现在不能做的是通过CXF从Web服务收到回复。 SSL握手似乎只是花花公子甚至达到了CXF尝试进行HTTP POST的程度,但是超时等待响应(如下所示):

 Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: false Is secure renegotiation: false *** HelloRequest (empty) main, SEND TLSv1 ALERT: warning, description = no_renegotiation Padded plaintext before ENCRYPTION: len = 24 0000: 01 64 01 FD 5B 38 03 A6 70 41 57 58 6D 75 60 F7 .d..[8..pAWXmu`. 0010: 93 1F 02 F3 C4 46 01 01 .....F.. main, WRITE: TLSv1 Alert, length = 24 [Raw write]: length = 29 0000: 15 03 01 00 18 0C 9B DF 1B 60 AB 12 EE C7 CF C9 .........`...... 0010: 62 97 A5 5D 5F 14 48 E1 9F AD 8A 08 05 b..]_.H...... main, handling exception: java.net.SocketTimeoutException: Read timed out main, called close() main, called closeInternal(true) main, SEND TLSv1 ALERT: warning, description = close_notify Padded plaintext before ENCRYPTION: len = 24 0000: 01 00 BD 99 7A 7C 72 1F BB 11 2D AB 3F 53 C9 CD ....zr..-.?S.. ... continuing on 

现在,如果我使用curl或类似的东西,我可以在不到一秒的时间内得到响应,所以我知道Web服务没有错。 下面是创建服务端口所需的全部代码,包括使用TLS和HTTP代理进行设置。 我有一个非常简单的JUnit测试来创建和运行它:

 public static MYPORT setupTLS(MYPORT port) throws IOException, GeneralSecurityException { HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(port) .getConduit(); String keyPassword = "password"; KeyStore keyStore = KeyStore.getInstance("pkcs12"); URL pkcs12_file = MECTPortFactory.class.getResource(System .getProperty("pkcs12.keyFile")); InputStream keyFile = pkcs12_file.openStream(); keyStore.load(keyFile, keyPassword.toCharArray()); KeyManager[] myKeyManagers = getKeyManagers(keyStore, keyPassword); TLSClientParameters tlsCP = new TLSClientParameters(); tlsCP.setKeyManagers(myKeyManagers); tlsCP.setDisableCNCheck(true); FiltersType cipher_suite_filter = new FiltersType(); cipher_suite_filter.getInclude().add("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); cipher_suite_filter.getExclude().add(".*_DH_anon_.*"); tlsCP.setCipherSuitesFilter(cipher_suite_filter); httpConduit.setTlsClientParameters(tlsCP); httpConduit.setClient(getHttpClient()); return port; } private static HTTPClientPolicy getHttpClient() { HTTPClientPolicy client_policy = new HTTPClientPolicy(); client_policy.setProxyServer("PROXY_SERVER_ADDRESS"); client_policy.setProxyServerPort(8080); client_policy.setAutoRedirect(true); client_policy.setConnection(ConnectionType.KEEP_ALIVE); client_policy.setAllowChunking(true); client_policy.setReceiveTimeout(10000); return client_policy; } private static KeyManager[] getKeyManagers(KeyStore keyStore, String keyPassword) throws GeneralSecurityException, IOException { String alg = KeyManagerFactory.getDefaultAlgorithm(); char[] keyPass = keyPassword != null ? keyPassword.toCharArray() : null; KeyManagerFactory fac = KeyManagerFactory.getInstance(alg); fac.init(keyStore, keyPass); return fac.getKeyManagers(); } 

编辑:

我已经摆弄了一些客户端设置,例如更改是否AutoRedirectAllowChunking等,没有任何差异,所以我不认为这会导致错误。

EDIT2:

我没有得到网络服务的回复。 如何排除故障并修复导致CXF超时而不是接收响应的原因?

我的天啊! 我想到了。

所以我穿过了互联网,发现了这个小gem:

如何使用客户端证书身份validation配置SoapUI

它引用了Oracle / Sun的一个非常重要的注释:

传输层安全性(TLS)重新协商问题自述文件

从对等方接收重新协商请求的应用程序将根据所处的连接类型进行响应:

TLSv1:类型为“no_renegotiation(100)”的警告警报消息将发送给对等方,连接将保持打开状态。

然后,进一步下来:

通过在初始化JSSE库之前将新系统属性sun.security.ssl.allowUnsafeRenegotiation设置为true ,可以为需要它的应用程序重新启用重新协商。 有几种方法可以设置此属性:

  1. 命令行:

    % java -Dsun.security.ssl.allowUnsafeRenegotiation=true Main

  2. Java控制面板(Java插件/ Java Web Start) – 运行时环境。

  3. 在申请中:

    java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", true);

请注意,除非客户端和服务器都启用了重新协商,否则不会发生TLS / SSL重新协商。

那么多空呢? System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");

和事情。 只是。 工作。