在结合 2waySSL 和代理的 Weblogic 10.3.6 中使用 JAX-WS
Using JAX-WS in Weblogic 10.3.6 combining 2waySSL and Proxy
我在 weblogic 10.3.6 中使用 JAX-WS 实现了一个连接到不同类型的 web 服务的连接器,该连接器可以配置 2waySSL,代理并将它们结合起来。
- 使用代理的实现使用 ClientProxyFeature 可以正常工作。
与 2waySSL 使用自定义 SSLSocketFactory 的方式相同,如 Oracle 在文档中所述。 Persisting the State of a Request over SSL (JAX-WS Only)
((BindingProvider) port).getRequestContext().put(
JAXWSProperties.SSL_SOCKET_FACTORY,
SSLClientUtil.getSSLSocketFactoryFromSysProperties());
合并这两个功能时会出现此问题。握手没有发生 (ClientHello)
错误是:
ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', READ: TLSv1.2 Alert, length = 64
Padded plaintext after DECRYPTION: len = 64
0000: F0 E5 6E 9F 6F F4 BB 2E 07 29 56 FE 34 0A 10 0B ..n.o....)V.4...
0010: 02 28 7E 75 92 F7 03 4E CD 3A 7E 0B E2 6A 7C 8E .(.u...N.:...j..
0020: 3B F8 4E F5 98 A3 D3 B4 67 76 20 49 1B 77 07 5E ;.N.....gv I.w.^
0030: 9D 66 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D .f..............
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', RECV TLSv1.2 ALERT: fatal, handshake_failure
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
<13-sep-2017 09H32' CEST> <Debug> <SecuritySSL> <BEA-000000> <[Thread[[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads]]weblogic.security.SSL.jsseadapter: SSLENGINE: Exception occurred during SSLEngine.unwrap(ByteBuffer,ByteBuffer[]).
javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:188)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1614)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1582)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1751)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1043)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:865)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:740)
调试和反编译weblogic源码发现使用proxy的HttpsClient没有使用自定义的SSLSocketFactory
1) 在传输中class weblogic.wsee.jaxws.transport.http.client.HttpClientTransport weblogic 打开连接:
protected HttpURLConnection openConnection(Packet paramPacket)
…
localSSLSocketFactory = (javax.net.ssl.SSLSocketFactory)this.context.invocationProperties.get("com.sun.xml.ws.transport.https.client.SSLSocketFactory");
if ((localSSLSocketFactory != null) && ((localSSLSocketFactory instanceof javax.net.ssl.SSLSocketFactory)))
{
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("set (jdk) ssl socketfactory to wls socketfactory");
}
((weblogic.net.http.HttpsURLConnection)localObject3).setSSLSocketFactory(new MySSLSocketFactory((javax.net.ssl.SSLSocketFactory)localSSLSocketFactory));
}
…
如您所见,设置自定义 SSLSocketFactory。
2) 在没有代理的情况下,weblogic.net.http.HttpsClient 使用自定义 SSLSocketFactory 来创建套接字
this.serverSocket = localSocketFactory.createSocket(arrayOfInetAddress[i], paramInt);
localSocketFactory 是自定义 SSLSocketFactory。
3) 但是如果使用代理则创建一个新的 SSLSocketFactory
private void makeConnectionUsingProxy(String s, int i, boolean flag)
throws IOException
{
javax.net.ssl.SSLSocketFactory sslsocketfactory;
int j;
SSLContextWrapper sslcontextwrapper = SSLSetup.getSSLContext(sslInfo);
sslcontextwrapper.getHostnameVerifier().setProxyMapping(s, host);
sslcontextwrapper.getTrustManager().setProxyMapping(s, host);
sslsocketfactory = sslcontextwrapper.getSSLSocketFactory();
sslInfo 是一个对象,没有在 SSLSocketFactory 中通知的密钥库或信任库。我还没有看到任何方式来通知对象 sslInfo (weblogic.security.SSL.SSLClientInfo)
启动weblogic的变量是下一个:
-Dweblogic.security.SSL.nojce=true -Djavax.net.debug=all -Dssl.debug=true
-Djavax.net.ssl.keyStore=XXXXXs -Djavax.net.ssl.keyStorePassword=XXXXX
-Djdk.tls.enableRC4CipherSuites=true -Djsse.enableSNIExtension=false -Dweblogic.ssl.JSSEEnabled=true -Dweblogic.security.SSL.enableJSSE=true -Dweblogic.security.SSL.nojce=true -Dweblogic.security.SSL.ignoreHostnameVerification=true
自定义 SSLSocketFactory 是使用此参数和默认信任库创建的。当没有使用代理时,一切正常。
我不明白为什么与代理 weblogic 建立连接时不使用相同的 SSLSocketFactory。
有什么想法吗?
Oracle 人员已经确认我们在这个实现中是 "bug",只能用 属性 -DUseSunHttpHandler=true.
来解决
在 Oracle 12 中,您可以使用 ClientProxyFeature 的 setter 方法 setUseSunHttpHandler。但是用weblogic实现是无法解决的。
我在 weblogic 10.3.6 中使用 JAX-WS 实现了一个连接到不同类型的 web 服务的连接器,该连接器可以配置 2waySSL,代理并将它们结合起来。
- 使用代理的实现使用 ClientProxyFeature 可以正常工作。
与 2waySSL 使用自定义 SSLSocketFactory 的方式相同,如 Oracle 在文档中所述。 Persisting the State of a Request over SSL (JAX-WS Only)
((BindingProvider) port).getRequestContext().put( JAXWSProperties.SSL_SOCKET_FACTORY, SSLClientUtil.getSSLSocketFactoryFromSysProperties());
合并这两个功能时会出现此问题。握手没有发生 (ClientHello)
错误是:
ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', READ: TLSv1.2 Alert, length = 64
Padded plaintext after DECRYPTION: len = 64
0000: F0 E5 6E 9F 6F F4 BB 2E 07 29 56 FE 34 0A 10 0B ..n.o....)V.4...
0010: 02 28 7E 75 92 F7 03 4E CD 3A 7E 0B E2 6A 7C 8E .(.u...N.:...j..
0020: 3B F8 4E F5 98 A3 D3 B4 67 76 20 49 1B 77 07 5E ;.N.....gv I.w.^
0030: 9D 66 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D .f..............
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', RECV TLSv1.2 ALERT: fatal, handshake_failure
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)', fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
<13-sep-2017 09H32' CEST> <Debug> <SecuritySSL> <BEA-000000> <[Thread[[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads]]weblogic.security.SSL.jsseadapter: SSLENGINE: Exception occurred during SSLEngine.unwrap(ByteBuffer,ByteBuffer[]).
javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:188)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1614)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1582)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1751)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1043)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:865)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:740)
调试和反编译weblogic源码发现使用proxy的HttpsClient没有使用自定义的SSLSocketFactory
1) 在传输中class weblogic.wsee.jaxws.transport.http.client.HttpClientTransport weblogic 打开连接:
protected HttpURLConnection openConnection(Packet paramPacket)
…
localSSLSocketFactory = (javax.net.ssl.SSLSocketFactory)this.context.invocationProperties.get("com.sun.xml.ws.transport.https.client.SSLSocketFactory");
if ((localSSLSocketFactory != null) && ((localSSLSocketFactory instanceof javax.net.ssl.SSLSocketFactory)))
{
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("set (jdk) ssl socketfactory to wls socketfactory");
}
((weblogic.net.http.HttpsURLConnection)localObject3).setSSLSocketFactory(new MySSLSocketFactory((javax.net.ssl.SSLSocketFactory)localSSLSocketFactory));
}
…
如您所见,设置自定义 SSLSocketFactory。
2) 在没有代理的情况下,weblogic.net.http.HttpsClient 使用自定义 SSLSocketFactory 来创建套接字
this.serverSocket = localSocketFactory.createSocket(arrayOfInetAddress[i], paramInt);
localSocketFactory 是自定义 SSLSocketFactory。
3) 但是如果使用代理则创建一个新的 SSLSocketFactory
private void makeConnectionUsingProxy(String s, int i, boolean flag)
throws IOException
{
javax.net.ssl.SSLSocketFactory sslsocketfactory;
int j;
SSLContextWrapper sslcontextwrapper = SSLSetup.getSSLContext(sslInfo);
sslcontextwrapper.getHostnameVerifier().setProxyMapping(s, host);
sslcontextwrapper.getTrustManager().setProxyMapping(s, host);
sslsocketfactory = sslcontextwrapper.getSSLSocketFactory();
sslInfo 是一个对象,没有在 SSLSocketFactory 中通知的密钥库或信任库。我还没有看到任何方式来通知对象 sslInfo (weblogic.security.SSL.SSLClientInfo)
启动weblogic的变量是下一个:
-Dweblogic.security.SSL.nojce=true -Djavax.net.debug=all -Dssl.debug=true
-Djavax.net.ssl.keyStore=XXXXXs -Djavax.net.ssl.keyStorePassword=XXXXX
-Djdk.tls.enableRC4CipherSuites=true -Djsse.enableSNIExtension=false -Dweblogic.ssl.JSSEEnabled=true -Dweblogic.security.SSL.enableJSSE=true -Dweblogic.security.SSL.nojce=true -Dweblogic.security.SSL.ignoreHostnameVerification=true
自定义 SSLSocketFactory 是使用此参数和默认信任库创建的。当没有使用代理时,一切正常。
我不明白为什么与代理 weblogic 建立连接时不使用相同的 SSLSocketFactory。
有什么想法吗?
Oracle 人员已经确认我们在这个实现中是 "bug",只能用 属性 -DUseSunHttpHandler=true.
来解决在 Oracle 12 中,您可以使用 ClientProxyFeature 的 setter 方法 setUseSunHttpHandler。但是用weblogic实现是无法解决的。