Java 无法使用 cxf http-conduit 连接 SSL 网络服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24042784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unable to connect SSL webservice with cxf http-conduit
提问by franzke
I am trying to connect to a SOAP webservice and need to provide a cert for authentication. I am currently using the cxf http conduit to locate my certificate. I received a p12 file from the service I am wanting to call. I have imported the p12 into a jks. I put the jks in the class path along with my cxf.xml page. I've modified my web.xml to contain the context-param and the listener-class, but I am still getting logs from the server saying no certificate provided. I've looked all over for solutions but nothing has worked this far. Any help is greatly appreciated
我正在尝试连接到 SOAP 网络服务并且需要提供用于身份验证的证书。我目前正在使用 cxf http 管道来定位我的证书。我从要调用的服务中收到了一个 p12 文件。我已将 p12 导入 jks。我将 jks 与我的 cxf.xml 页面一起放在类路径中。我已经修改了我的 web.xml 以包含上下文参数和侦听器类,但我仍然从服务器获取日志,说没有提供证书。我已经四处寻找解决方案,但到目前为止没有任何效果。任何帮助是极大的赞赏
CXF.XML
CXF文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/configuration/security
http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<http:conduit name="*.http-conduit">
<http:tlsClientParameters>
<sec:keyManagers keyPassword="changeit">
<sec:keyStore type="JKS" password="changeit"
resource="myKeystore.jks"
/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="changeit"
resource="myKeystore.jks"/>
</sec:trustManagers>
<sec:cipherSuitesFilter>
<!-- these filters ensure that a ciphersuite with
export-suitable or null encryption is used,
but exclude anonymous Diffie-Hellman key change as
this is vulnerable to man-in-the-middle attacks -->
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_AES_.*</sec:include>
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
</http:tlsClientParameters>
<http:client AutoRedirect="true" Connection="Keep-Alive"/>
</http:conduit>
</beans>
WEB.XML
网页.XML
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
采纳答案by user1516873
I agree with @hooknc last comment. Make sure your keystore contains private key entry. Also, set privatekey password equal to keystore password. You can test your service with code listed below. I wrote it for cxf version 3.0.0-milestone2, because i need multiple signatures, but i think code should work also with stable branch 2.x
我同意@hooknc 最后的评论。确保您的密钥库包含私钥条目。此外,设置私钥密码等于密钥库密码。您可以使用下面列出的代码测试您的服务。我是为 cxf 版本 3.0.0-milestone2 编写的,因为我需要多个签名,但我认为代码应该也适用于稳定分支 2.x
private PaymentService_Service service = null;
private PaymentService iface = null;
@Before
public void setUp() throws Exception {
System.setProperty("com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true");
System.setProperty("javax.net.debug", "ssl");
service = new PaymentService_Service();
iface = service.getPaymentServiceImplPort();
Client client = ClientProxy.getClient(iface);
HTTPConduit http = (HTTPConduit) client.getConduit();
TLSClientParameters parameters = new TLSClientParameters();
parameters.setSSLSocketFactory(createSSLContext().getSocketFactory());
http.setTlsClientParameters(parameters);
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setReceiveTimeout(32000);
http.setClient(httpClientPolicy);
}
private SSLContext createSSLContext() throws Exception{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(new FileInputStream("/home/user/dev/project/key/http.jks"), "changeit".toCharArray());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream("/home/user/dev/project/key/client.jks"), "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, "changeit".toCharArray());
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers() , tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}
@Test
public void testSomeMethod() throws Exception {
Client client = ClientProxy.getClient(iface);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
String res = iface.doSomeMethod();
}
回答by hooknc
I don't believe just putting the truststore (jks) in your classpath will work the way you think it will. I'm fairly confident that you will need to call our the truststore that you wish to use via vm options.
我不相信仅仅将信任库 (jks) 放在您的类路径中就会像您认为的那样工作。我相当有信心,您需要通过 vm 选项调用我们希望使用的信任库。
Add -Djavax.net.ssl.trustStore={file_path_to_your_jks} to your application's VM arguments. You might also need to use -Djavax.net.ssl.trustStorePassword={your_jks_password} if the default password of 'changeit' wasn't used.
将 -Djavax.net.ssl.trustStore={file_path_to_your_jks} 添加到应用程序的 VM 参数。如果未使用“changeit”的默认密码,您可能还需要使用 -Djavax.net.ssl.trustStorePassword={your_jks_password}。