Error accessing a Web Service with SSL

2019-02-03 10:13发布

问题:

I have a program that is supposed to send a file to a web service, which requires an SSL connection. I run the program as follows:

SET JAVA_HOME=C:\Program Files\Java\jre1.6.0_07
SET com.ibm.SSL.ConfigURL=ssl.client.props
"%JAVA_HOME%\bin\java" -cp ".;Test.jar" ca.mypackage.Main

This was works fine, but when I change the first line to

SET JAVA_HOME=C:\Program Files\IBM\SDP\runtimes\base_v7\java\jre

I get the following error:

com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: java.net.SocketException: java.lang.ClassNotFoundException: Cannot find the specified class com.ibm.websphere.ssl.protocol.SSLSocketFactory
at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:119)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:140)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:86)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:593)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:552)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:537)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:434)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:247)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:132)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:242)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:222)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:115)
at $Proxy26.fileSubmit(Unknown Source)
at com.testing.TestingSoapProxy.fileSubmit(TestingSoapProxy.java:81)
at ca.mypackage.Main.main(Main.java:63)
Caused by: java.net.SocketException: java.lang.ClassNotFoundException: Cannot find the specified class com.ibm.websphere.ssl.protocol.SSLSocketFactory
at javax.net.ssl.DefaultSSLSocketFactory.a(SSLSocketFactory.java:7)
at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:1)
at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:110)
at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:14)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:902)
at com.ibm.net.ssl.www2.protocol.https.b.getOutputStream(b.java:86)
at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:107)
... 14 more
Caused by: java.lang.ClassNotFoundException: Cannot find the specified class com.ibm.websphere.ssl.protocol.SSLSocketFactory
at javax.net.ssl.SSLJsseUtil.b(SSLJsseUtil.java:20)
at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:36)
at javax.net.ssl.HttpsURLConnection.getDefaultSSLSocketFactory(HttpsURLConnection.java:16)
at javax.net.ssl.HttpsURLConnection.<init>(HttpsURLConnection.java:36)
at com.ibm.net.ssl.www2.protocol.https.b.<init>(b.java:1)
at com.ibm.net.ssl.www2.protocol.https.Handler.openConnection(Handler.java:11)
at java.net.URL.openConnection(URL.java:995)
at com.sun.xml.internal.ws.api.EndpointAddress.openConnection(EndpointAddress.java:206)
at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.createHttpConnection(HttpClientTransport.java:277)
at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(HttpClientTransport.java:103)
... 14 more

So it seems that this problem would be related to the JRE I'm using, but what doesn't seem to make sense is that the non-IBM JRE works fine, but the IBM JRE does not. Any ideas, or suggestions?

回答1:

If your non IBM jre is sun, then it already comes with SSL classes implementation packaged along with it.

It seems the IBM jre is not containing SSL implementation classes at all.



回答2:

Try adding these two lines somewhere in your setup code:

Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");


回答3:

Java only allows one SSL connection factory class for a JVM. If you are using a JDK thats shipped with WebSphere Application Server v6x/7x/8x or any other WebSphere server tools in Rational Application Developer, then those require IBM ( com.ibm.websphere.ssl.protocol.SSLSocketFactory ) specific class from WebSphere Application Server runtime. because the java security file has the JSSE socket factories set like below

# Default JSSE socket factories
#ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl
#ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl

# WebSphere socket factories (in cryptosf.jar)
ssl.SocketFactory.provider=com.ibm.websphere.ssl.protocol.SSLSocketFactory
ssl.ServerSocketFactory.provider=com.ibm.websphere.ssl.protocol.SSLServerSocketFactory

So, If you uncomment the Default JSSE Socket factories and comment out the WebSphere ones then WAS is going to puke.

Better work around would be to have com.ibm.ws.security.crypto.jar file in your class path. This jar file has a dependency on com.ibm.ffdc.jar file so you need that in your class path well. Both these jarfiles are available under <WebSphere_Install_Dirctory>/plugins/



回答4:

one may set these properties at WAS_HOME/*/java/jre/lib/security/java.security file by uncomenting the following JSSE props.

Default JSSE socket factories

ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl



回答5:

One more "solution" which seems to be working for me. Create your own security properties file, my.java.security with contents like:

ssl.SocketFactory.provider=
ssl.ServerSocketFactory.provider=

When calling Java (or in my case maven), add the command line option:

-Djava.security.properties=C:\myfiles\my.java.security

Cribbed from the IBM Liberty documentation: http://www-01.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/rwlp_trouble.html?lang=en



回答6:

Found this topic while searching for the same error message but found a different solution. To test a https REST service using the Apache Wink client:

ClientConfig config = new ClientConfig();
config.setBypassHostnameVerification(true);
RestClient client = new RestClient(config);

And set the Factory's empty:

Security.setProperty("ssl.SocketFactory.provider", "");
Security.setProperty("ssl.ServerSocketFactory.provider", "");

My runtime is a standalone Camel test using IBM JRE 1.7 from IBM WebSphere v8.5.5.



回答7:

I had a similar issue when my Batch application was trying to fetch data from Restful web service using Apache wink. I was using MyEclipse as my dev environment. And was using the jre provided by IBM webSphere 8.5. When I changed to Sun 1.6 jre, the issue got resolved.