Wildfly:如何使用JAXWS-RI代替Apache CXF(仅WebService客户端)


问题内容

我的环境是作为应用程序服务器的Maven项目和Wildfly(8.2.1)。我需要使用SOAP将传入的REST调用与第三方服务器连接。我需要SSL客户端身份验证;因此,我有自己的KeyStore和TrustStore。因此,我创建了自己的SSLContext,需要让WebService使用此SSLContext。

一切看起来像这样:

// 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);

如果我从JUnit测试中调用此代码,则一切正常。它使用来自JRE的JAXWS-RI。

如果我从Wildfly调用此代码,即从传入的REST调用(最终需要触发该请求),则该代码将不起作用,因为它不使用自己的SSLContext。它使用默认的SSLContext,当然它会被第三方SOAP服务器拒绝。我看到的是它不使用JAXWS-
RI,而是使用Apache
CXF作为JAXWS实现。因此,我想这bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory());根本就被忽略了[
为什么?],并且没有任何效果。(我也尝试过com.sun.xml.ws.transport.https.client.SSLSocketFactory[没有internal]
的属性名称-也没有运气。)

我知道,我可以使用HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()),甚至使用JVM参数javax.net.ssl.trustStorejavax.net.ssl.keyStore(以及它们相应的密码属性)。由于这会影响所有连接,因此使用此解决方案已不再讨论。但是,让我看看会发生什么,如果我仍然使用它:

  • JUnit用例:它也可以工作

  • Wildfly用例:似乎JAXWS使用SSLContext,但是有一个SSL异常(服务器发出的有关CA未知的警报)。这表明建立连接的方式甚至存在差异。如果代码是使用JUnit执行的,为什么它能正常工作?这证明密钥库/信任库已使用正确的证书正确设置。是不是

编辑:
还有一个证明,问题是Wildfly使用的JAXWS实现:如果我只是执行一个简单的HttpsConnection,它甚至可以在Wildfly中与我自己的KeyStore
/ TrustStore一起使用:

url = new URL("https://hostname:443/.../...");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(sc.getSocketFactory());
System.out.println(Utils.inputStreamToString(con.getInputStream()));

那么最好的办法是什么?->作为问题标题,我想尝试使Wildfly也使用JAXWS-RI而不是Apache
CXF。但是直到现在我还是不工作。我试图将以下依赖项放入pom中:

    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.2.10</version>
    </dependency>

但这给了我以下例外:

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]

怎么了?我如何才能使Wildfly以相同的方式工作,就好像代码是从同一项目中执行但“作为JUnit测试”执行的一样?

编辑: 如果您有技巧如何以不同的方式(前提是这是一种干净的Java EE解决方案,即不发送自己的XML主体)来达到目标​​(在Wildfly
8.2.1上使用SSL和客户端认证使用SOAP请求发送SOAP请求) ),而不是像Axis 1)这样的旧框架,也欢迎使用! 我确实很快需要解决方案-
我已经战斗了好几天…


问题答案:

好的,最后,我放弃了尝试替换使用的JAX-WS实现。我得到它来正确设置Apache CXF。

http://codingdict.com/questions/131380