【问题标题】:Two-way SSL between two applications on the same Tomcat Server同一 Tomcat 服务器上的两个应用程序之间的双向 SSL
【发布时间】:2014-03-07 20:52:28
【问题描述】:

我有以下场景:两个 Java 应用程序在同一个 Tomcat 服务器上运行——我们称它们为 App A 和 App B——它们需要通过已经在 App 上运行的 web 服务相互通信A. 此 Web 服务仅接受经过身份验证的客户端 (clientAuth="true")。

全部配置好后,我的Tomcat作为客户端,发送一个空的证书链给服务器(就是同一个Tomcat)。这就是我所做的。

我使用 keytool 为服务器生成了一个自签名证书:

keytool -genkeypair -keyalg RSA -keysize 2048 -keystore keystore.jks -alias server

然后导出这个证书:

keytool -exportcert -keystore keystore.jsk -alias server -file server.crt

并将其添加到信任库:

keytool -importcert -keystore truststore.jsk -alias server -file server.crt

SSL协商如下:

  1. 客户打招呼
  2. 服务器打招呼并出示其证书(上面生成) 客户
  3. 客户端接受它(因为它在信任库中)
  4. 服务器通过提供有效 DN 列表(其中包含单个条目,即上面生成的证书)来要求客户端证书
  5. 客户端以某种方式确定它没有有效的证书并发送一个空的证书链
  6. SSL 握手失败

我没有发布实际的 SSL 日志,因为客户端和服务器是同一个 Tomcat,所以一切都是一团糟。

我在这里做错了什么?请记住,这两个应用程序位于同一台服务器上,并且证书是自签名的。我还做了一个测试,我生成了另一个自签名证书,将其导出到一个 .p12 文件并安装在我的浏览器中,然后通过 URL 直接在地址框中调用 Web 服务,它运行良好。

谢谢!

【问题讨论】:

  • 问题不在于密钥,而在于您如何初始化 App B 使用的 HTTPS 连接/Web 服务客户端。
  • @Robert 我使用 wsimport 命令生成的存根,它使用 WSDL url(以“https”开头并使用端口 8443,正确配置)。在我的代码中,我使用了这个:MyWebService service = new MyWebService(url); IMyWebService client = service.getMyWebServicePort(); client.myMethod(...); MyWebService 这个类扩展了 javax.xml.ws.Service。

标签: java web-services tomcat ssl https


【解决方案1】:

记录到这里的任何人......

我可以通过两种方式做到这一点。一种是为我的客户端应用程序准备一个特殊的配置文件,名为 cxf.xml,如 in this link 所述。另一种是使用代码强制加载配置,如下:

@WebEndpoint(name = "MyWebServicePort")
public IMyWebService getMyWebServicePort() {
    IMyWebService port = super.getPort(new QName("http://my.namespace/", "MyWebServicePort"), IMyWebService.class);
    try {
        // loads keymanager
        File keyStoreFile = new File(System.getProperty("javax.net.ssl.keyStore"));
        String keyStorePass = System.getProperty("javax.net.ssl.keyStorePassword");

        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream(keyStoreFile), keyStorePass.toCharArray());

        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyFactory.init(keyStore, keyStorePass.toCharArray());

        KeyManager[] km = keyFactory.getKeyManagers();


        // loads trustmanager
        File trustStoreFile = new File(System.getProperty("javax.net.ssl.trustStore"));
        String trustStorePass = System.getProperty("javax.net.ssl.trustStorePassword");

        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream(trustStoreFile), trustStorePass.toCharArray());

        TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(trustStore);

        TrustManager[] tm = trustFactory.getTrustManagers();

        // configuring the connection
        Client cxfClient = ClientProxy.getClient(port);
        HTTPConduit httpConduit = (HTTPConduit) cxfClient.getConduit();

        TLSClientParameters tlsParams = httpConduit.getTlsClientParameters();
        if (tlsParams == null) {
            tlsParams = new TLSClientParameters();
        }
        tlsParams.setKeyManagers(km);
        tlsParams.setTrustManagers(tm);

        httpConduit.setTlsClientParameters(tlsParams);
    } catch (Exception e) {
        ...
    }

    return port;
}

我真的不知道为什么它没有加载默认配置(使用 JVM 参数)。谜底:调试,我发现在建立SSL连接时,它实际上使用了DummyX509KeyManager,意味着没有加载配置。可能是一个错误?我不知道。

【讨论】:

    猜你喜欢
    • 2012-12-28
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 2012-02-14
    • 2013-08-07
    • 1970-01-01
    • 2019-05-19
    • 2012-12-20
    相关资源
    最近更新 更多