Java 无法将SSL webservice与cxf http管道连接
我正在尝试连接到SOAP Web服务,需要提供用于身份验证的证书。我目前正在使用cxf http管道查找我的证书。我收到了一个p12文件从服务,我想打电话。我已将p12导入jks。我将jk与我的cxf.xml页面一起放在类路径中。我已经修改了web.xml以包含context参数和listener类,但是我仍然从服务器获取日志,说没有提供证书。我到处寻找解决办法,但到目前为止没有任何办法。非常感谢您的帮助 CXF.XMLJava 无法将SSL webservice与cxf http管道连接,java,cxf,pkcs#12,http-conduit,Java,Cxf,Pkcs#12,Http Conduit,我正在尝试连接到SOAP Web服务,需要提供用于身份验证的证书。我目前正在使用cxf http管道查找我的证书。我收到了一个p12文件从服务,我想打电话。我已将p12导入jks。我将jk与我的cxf.xml页面一起放在类路径中。我已经修改了web.xml以包含context参数和listener类,但是我仍然从服务器获取日志,说没有提供证书。我到处寻找解决办法,但到目前为止没有任何办法。非常感谢您的帮助 CXF.XML <beans xmlns="http://www.springfra
<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>
.*u导出*
*.\u导出1024\u*
带有“DES”的**
.*u与\u AES\u*
带有空值的*u*
.*DH_anon_*
WEB.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>
上下文配置位置
类路径:cxf.xml
org.springframework.web.context.ContextLoaderListener
我不相信仅仅将信任库(jks)放在类路径中就能按照您认为的方式工作。我很有信心,您需要通过虚拟机选项将我们的信任库呼叫给您希望使用的信任库
将-Djavax.net.ssl.trustStore={file_path_to_your_jks}添加到应用程序的VM参数中。如果没有使用“changeit”的默认密码,您可能还需要使用-Djavax.net.ssl.trustStorePassword={your_jks_password}。我不相信仅仅将信任库(jks)放在类路径中就能按您认为的方式工作。我很有信心,您需要通过虚拟机选项将我们的信任库呼叫给您希望使用的信任库
将-Djavax.net.ssl.trustStore={file_path_to_your_jks}添加到应用程序的VM参数中。如果没有使用“changeit”的默认密码,您可能还需要使用-Djavax.net.ssl.trustStorePassword={your_jks_password}。我同意@hooknc的最后一条评论。确保您的密钥库包含私钥条目。另外,将privatekey密码设置为等于密钥库密码。您可以使用下面列出的代码测试您的服务。我是为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();
}
我同意@hooknc最后的评论。确保您的密钥库包含私钥条目。另外,将privatekey密码设置为等于密钥库密码。您可以使用下面列出的代码测试您的服务。我是为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();
}
如果我要在我的jre中将信任证书添加到cacerts,我还需要添加VM参数吗?如果将新证书添加到默认cacerts,则不需要VM参数,但我强烈建议不要使用该策略。如果您将该证书添加到基本cacerts中,那么您机器上运行的所有java应用程序都将信任该新证书。这可能不会太有害,但它不是超级安全的。此外,当您更新java版本时,您必须记住再次重新安装该证书。但是,同样,当您更新java版本时,您应该重新复制cacerts并重新导入证书。然后,我是否需要在cxf.xml中更改http管道中信任库的路径以指向cacerts?因此,我直到刚才才知道cxf是什么,但是快速浏览一下他们的文档,他们解释了如何定义信任库:通过使用“keytool-list-v-keystore”命令确保密钥库是AOK的。其他尝试事项:使用密钥库和信任库的完整路径(而不仅仅是类路径)。看起来您的密钥库和信任库是同一个文件,这没关系,但我通常会尝试将两者分开。密钥库包含您的客户端证书,而信任库将包含您信任的证书和CA。如果我要将信任证书添加到jre中的cacerts,是否仍需要添加VM参数?如果将新证书添加到默认cacerts,则不需要VM参数,但我强烈反对这种策略。如果您将该证书添加到基本cacerts中,那么您机器上运行的所有java应用程序都将信任该新证书。这可能不会太有害,但它不是超级安全的。此外,当您更新java版本时,您必须记住再次重新安装该证书。但是,同样,当您更新java版本时,您应该重新复制cacerts并重新导入证书。然后,我是否需要在cxf.xml中更改http管道中信任库的路径以指向cacerts?因此,我直到刚才才知道cxf是什么,但是快速浏览一下他们的文档,他们解释了如何定义信任库:通过使用“keytool-list-v-keystore”命令确保密钥库是AOK的。其他尝试事项:使用密钥库和信任库的完整路径(而不仅仅是类路径)。看起来您的密钥库和信任库是同一个文件,这没关系,但我通常会尝试将两者分开。密钥库包含您的客户端证书,而信任库将包含您信任的证书和CA。