Java 如何创建两个Tomcat在Tomcat之间使用https时会满意的自签名证书?

Java 如何创建两个Tomcat在Tomcat之间使用https时会满意的自签名证书?,java,tomcat,ssl,https,openssl,Java,Tomcat,Ssl,Https,Openssl,我正在尝试在两个tomcat服务器之间使用https。很遗憾,自签名证书导致此错误: Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:

我正在尝试在两个tomcat服务器之间使用https。很遗憾,自签名证书导致此错误:

Caused by: javax.net.ssl.SSLHandshakeException: 
           sun.security.validator.ValidatorException: PKIX path building failed: 
           sun.security.provider.certpath.SunCertPathBuilderException: 
                      unable to find valid certification path to requested target
具体来说,我有一个主tomcat和一些从tomcat服务器。主服务器使用简单的HttpURLConnection从servlet进行通信

使用我自己生成的证书颁发机构创建自签名证书的最简单方法是什么,这样每次添加新服务器时,我都不需要更改主tomcat服务器。

我可以访问openssl和Java7密钥工具

请参考我以前的配置:

server.xml连接器:

<Connector port="443" maxHttpHeaderSize="8192" maxThreads="150" 
    minSpareThreads="25" maxSpareThreads="75" enableLookups="false" 
    disableUploadTimeout="true" acceptCount="100" debug="0" scheme="https" 
    secure="true" clientAuth="false" sslProtocol="TLS" keystoreType="PKCS12" 
    keystoreFile="/usr/java/apache-tomee-plus/conf/keystore.ks" 
    keystorePass="XXX_SSL" truststoreType="JKS" 
    truststoreFile="/usr/java/apache-tomee-plus/conf/truststore.ks" 
    SSLEnabled="true" maxPostSize="0"/>
conf/jaas.conf

josso {
  org.josso.tc55.agent.jaas.SSOGatewayLoginModule required debug=true;
};
它仅用于传统支持,将被逐步淘汰。我不确定它是否可以加载,因为它是为Tomcat5.5构建的

在代码中,我通过使用以下HostnameVerifier()避免了在CN=中使用IP地址的问题

------------更新---------------

这已经通过与@Bruno的长时间讨论解决了,请使用他的原始帖子和我们的长时间聊天讨论


最后,我使用工具Keytool Explorer和XCA使我更容易学习和执行。

为了回答您的问题,我认为您不需要证书链。我已经将tomcat与自签名服务器证书一起使用,并与另一个自签名客户端证书连接。我不知道托米的情况,但我想也是一样

为了帮助您了解发生了什么,我考虑了以下可能的调试操作:

  • 在进入自动化之前,试着让事情在没有脚本的情况下正常工作。生成正确的配置将更容易

  • 确保脚本正确运行:检查存储区的tje内容是否符合预期,并确保server.xml文件指向正确的文件

  • 如果可以,尝试使用浏览器客户端身份验证单独测试服务器


最重要的是,确保服务器之间确实需要https。如果您处于受保护的领域,您可能过度使用了安全性,只是降低了应用程序的速度。

首先,您实际上并没有建立服务器到服务器的连接:这些连接仍然是客户端到服务器的连接。碰巧您的客户机是在servlet容器中运行的webapp

这很重要,因为建立连接将使用客户端信任设置。这些与Tomcat连接器上的信任设置不同

客户端webapp如何使用其信任设置取决于其实现方式和使用的库。公平地说,大多数客户机都会使用默认的JRE设置,除非有特定的代码可以使用其他设置。如果没有任何设置,通常会使用JRE的
cacerts
文件(请参阅中的详细信息)。您还可以指定常用的
javax.net.ssl.*
属性(使用
-Djavax.net.ssl….
);这需要在
JAVA\u OPTS
中的catalina启动脚本文件(
.bat
.sh
取决于平台)中完成。这将影响此JRE实例中运行的默认值,因此它可能不是您的首选(您可能需要更具体的内容,只影响给定的webapp,但您需要知道该webapp是如何实现的,或者它可以使用哪些可能的选项)。不过,
中的设置将覆盖此设置(除非您也希望使用客户端证书身份验证,否则信任库设置并不重要)

如果您有许多系统,那么可能不值得使用自签名证书:每个客户机都需要将所有这些自签名证书导入其信任存储。相反,您可以创建自己的CA并仅导入该CA证书。(在本地部署中,一个顶级/根CA就足够了,不需要中间CA。)OpenSSL的
CA.pl
是构建小型CA的好脚本,但您可能会发现其他工具,如XCA或TinyCA更方便。(请注意,您通常可以直接在Java中使用
.p12
文件,使用
PKCS12
密钥库类型,而不是默认的JKS。对于PKCS#12存储,密钥库密码和密钥/密钥管理器密码相同。)

因为您使用的是IP地址而不是名称,所以还应该注意(与许多浏览器不同)。特别是,您的主题DN的CN中的IP地址将不起作用:它需要位于主题替代名称扩展名中(类型为IPAddress,而不是DNSname)


编辑:

首先,去掉该主机名验证器:它为所有将使用该默认验证器的
HttpsURLConnection
引入了一个针对MITM攻击的漏洞,包括可能与外部服务器的连接。您可以通过使用SAN中的IP地址来解决此问题

以下是您需要遵循的步骤:

  • 创建您的CA(例如,使用XCA)。将其证书(而非私钥)导出到
    mycacert.pem

  • 如果您的应用程序可能与其他服务建立HTTPS连接,请将默认的
    cacerts
    文件复制到新文件
    mytruststore.jks
    (如果您的应用程序没有建立任何其他连接,请不要复制该文件,
    keytool
    将创建该文件)

  • 使用
    keytool
    mycacert.pem
    导入
    mytruststore.jks

    keytool -import -keystore mytruststore.jks -alias my_alias_name -cert mycacert.pem
    
  • 您现在有了一个truststore,您可以在需要与这些服务器对话的所有客户端中安装它。(如果使用JRE更新了
    cacerts
    文件,则可能需要再次执行这些步骤。)

    • 在客户端中配置该信任库。在这里,这是在
      JAVA\u OPTS中的Catalina脚本中完成的<
      
      HostnameVerifier hv = new HostnameVerifier()
      {
          public boolean verify(String urlHostName, SSLSession session)
          {
              return true;
          }
      };
      HttpsURLConnection.setDefaultHostnameVerifier(hv);
      
      connection = (HttpURLConnection) servlet.openConnection();
      
      keytool -import -keystore mytruststore.jks -alias my_alias_name -cert mycacert.pem