【问题标题】:Unable to connect SSL webservice with cxf http-conduit无法使用 cxf http-conduit 连接 SSL Web 服务
【发布时间】:2014-06-04 16:28:47
【问题描述】:

我正在尝试连接到 SOAP 网络服务,并且需要提供证书以进行身份​​验证。我目前正在使用 cxf http 管道来查找我的证书。我从要调用的服务中收到了一个 p12 文件。我已将 p12 导入到 jks 中。我将 jks 与我的 cxf.xml 页面一起放在类路径中。我已经修改了我的 web.xml 以包含上下文参数和侦听器类,但我仍然从服务器获取日志说没有提供证书。我已经到处寻找解决方案,但到目前为止没有任何效果。非常感谢任何帮助

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>

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>

【问题讨论】:

    标签: java cxf pkcs#12 http-conduit


    【解决方案1】:

    我同意@hooknc 最后的评论。确保您的密钥库包含私钥条目。此外,将 privatekey 密码设置为等于 keystore 密码。您可以使用下面列出的代码测试您的服务。我为 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();
    }
    

    【讨论】:

      【解决方案2】:

      我不相信只是将信任库 (jks) 放在您的类路径中会按照您认为的方式工作。我相当有信心,您需要通过 vm 选项调用您希望使用的信任库。

      将 -Djavax.net.ssl.trustStore={file_path_to_your_jks} 添加到应用程序的 VM 参数中。如果未使用“changeit”的默认密码,您可能还需要使用 -Djavax.net.ssl.trustStorePassword={your_jks_password}。

      【讨论】:

      • 如果我要将信任证书添加到我的 jre 中的 cacerts,我还需要添加 VM 参数吗?
      • 如果将新证书添加到默认 cacerts 中,则不需要 vm 参数,但我强烈建议不要使用该策略。如果您将该证书添加到您的基本 cacerts,那么在您的机器上运行的所有 Java 应用程序都将信任该新证书。这可能不会太有害,但它并不是超级安全。此外,当您更新您的 java 版本时,您必须记住再次重新安装该证书。但是话又说回来,当您更新您的 java 版本时,您应该重新复制 cacerts 并重新导入证书。
      • 好的,有道理。然后我是否需要更改 cxf.xml 中 http-conduit 中信任库的路径以指向 cacerts?
      • 所以,我直到现在才知道 CXF 是什么,但是快速浏览一下他们的文档,他们解释了如何定义信任库:cxf.apache.org/docs/…
      • 使用“keytool -list -v -keystore ”命令确保密钥库是 AOK。其他要尝试的事情:使用密钥库和信任库的完整路径(而不仅仅是类路径)。看起来您的密钥库和信任库是同一个文件,这没关系,但我通常会尝试将两者分开。密钥库包含您的客户端证书,而信任库将包含您信任的证书和 CA。
      猜你喜欢
      • 1970-01-01
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 2017-01-17
      • 2020-09-13
      • 2014-04-02
      相关资源
      最近更新 更多