My environment is the Maven project and Wildfly (8.2.1) as an application server. I need to connect with an incoming REST call to a third-party server using SOAP. I need SSL Client authentication; so I have my own KeyStore and TrustStore. Therefore, I create my own SSLContext and should allow the WebService to use this SSLContext.
Everything looks like this:
// Build SSL context with own KeyManager / TrustManager SSLContext sc = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyStore ks = KeyStore.getInstance("JKS"); String password = "changeit"; ks.load(getClass().getResourceAsStream("/keystore"), password.toCharArray()); kmf.init(ks, password.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); // Now build webservice client MyWS_Service service = new MyWS_Service(null, new QName("http://...", "MyWS")); MyWS port = service.getMyWSSOAP(); BindingProvider bindingProvider = (BindingProvider) port; // set to use own SSLContext bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory()); // set endpoint bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://hostname:443/.../..."); // perform request respObj = port.myRequest(myRequestObj);
If I call this code from a JUnit test, everything works fine. It uses JAXWS-RI from JRE.
If I call this code from Wildfly, that is, from my incoming REST call, where I finally need to run this request, it does not work because it does not use its own SSLContext. It uses the default SSLC file, which, of course, is rejected by a third-party SOAP server. I see that it does not use JAXWS-RI, but Apache CXF as an implementation of JAXWS. Therefore, I assume that bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory()); just ignored [ Why? ] and has no effect. (I also tried the property name com.sun.xml.ws.transport.https.client.SSLSocketFactory [without internal ] - also no luck.)
I know that I could use HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()) or even use the JVM parameters javax.net.ssl.trustStore , javax.net.ssl.keyStore (and the corresponding password properties). Since this affects all connections, this solution is not used to use this solution; however, let's see what happens if I use it:
JUnit use case: it also works
Use case of Wildfly: it seems that JAXWS is using SSLContext, but there is an SSL exception (warning from the server that the CA is unknown). This shows that there is even a difference in how to establish a connection. Why does it work if the code is executed using JUnit? This confirms that KeyStore / TrustStore is configured correctly with the correct certificates. Is not it?
Edit: There is further evidence that the problem is with the JAXWS implementation. Wildfly uses: if I just run a simple HttpsConnection, it even works with my own Wildfly key store / TrustStore:
url = new URL("https://hostname:443/.../..."); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setSSLSocketFactory(sc.getSocketFactory()); System.out.println(Utils.inputStreamToString(con.getInputStream()));
So what is the best thing to do? → As the name of the questions, I would like to try to bring Wildfly to use JAXWS-RI, not Apache CXF. But I still haven't worked. I tried to install the following dependency in pom:
<dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-rt</artifactId> <version>2.2.10</version> </dependency>
But this gives me the following exception:
java.util.ServiceConfigurationError: javax.xml.ws.spi.Provider: Provider com.sun.xml.ws.spi.ProviderImpl could not be instantiated at java.util.ServiceLoader.fail(ServiceLoader.java:232) ~[?:1.8.0_92]
What's wrong? How can I get Wildfly to work as if it were executing from the same project, but "like a JUnit test"?
Edit: If you have a hint on how to achieve the goal (sending SOAP requests using SSL with the auth client to Wildfly 8.2.1) in a different way (provided that it is a pure Java EE solution, that is, it does not send its own XML objects :-) and not with too old frames such as Axis 1) are also welcome! I soon need a solution - I'm afraid for several days ...