同一Tomcat服务器上两个应用程序之间的双向SSL

时间:2014-02-10 13:33:16

标签: java web-services tomcat ssl https

我有以下场景:两个Java应用程序在同一个Tomcat服务器上运行 - 让我们称之为App A和App B - 他们需要通过已在App上启动并运行的Web服务相互通信答:此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握手失败
  7. 我没有发布实际的SSL日志,因为客户端和服务器是相同的Tomcat,所以一切都混乱了。

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

    谢谢!

1 个答案:

答案 0 :(得分:0)

为了到达这里的任何人的记录......

我能够以两种方式做到这一点。一种是为我的客户端应用程序准备一个特殊的配置文件,名为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,这意味着没有加载配置。可能是一个错误?我不知道。