Java 无法将SSL webservice与cxf http管道连接

Java 无法将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

我正在尝试连接到SOAP Web服务,需要提供用于身份验证的证书。我目前正在使用cxf http管道查找我的证书。我收到了一个p12文件从服务,我想打电话。我已将p12导入jks。我将jk与我的cxf.xml页面一起放在类路径中。我已经修改了web.xml以包含context参数和listener类,但是我仍然从服务器获取日志,说没有提供证书。我到处寻找解决办法,但到目前为止没有任何办法。非常感谢您的帮助

CXF.XML

<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。