如何在Java Tomcat(Liferay)中为SMTP、外部JSON API和MySQL JDBC配置具有不同SSL配置的不同接口/上下文?

如何在Java Tomcat(Liferay)中为SMTP、外部JSON API和MySQL JDBC配置具有不同SSL配置的不同接口/上下文?,java,mysql,ssl,tomcat,ssl-certificate,Java,Mysql,Ssl,Tomcat,Ssl Certificate,我们在环境中使用Liferay应用程序。这是一个Java CMS软件,我们使用Tomcat 9部署了它。在我们的应用程序中,需要使用以下接口: 我们通过SSL通过外部SMTP邮件网关发送电子邮件。该网关具有“特殊”SSL证书链 我们还有一个外部JSON API,它需要SSL和证书身份验证!该接口有自己的“特殊”SSL证书链 我们还使用了一个托管的MySQL数据库实例,还有一个要求,这个数据库必须通过SSL连接 现在,为了能够通过SSL使用SSL邮件网关和外部JSON API进行证书身份验证,

我们在环境中使用Liferay应用程序。这是一个Java CMS软件,我们使用Tomcat 9部署了它。在我们的应用程序中,需要使用以下接口:

  • 我们通过SSL通过外部SMTP邮件网关发送电子邮件。该网关具有“特殊”SSL证书链
  • 我们还有一个外部JSON API,它需要SSL和证书身份验证!该接口有自己的“特殊”SSL证书链
  • 我们还使用了一个托管的MySQL数据库实例,还有一个要求,这个数据库必须通过SSL连接
现在,为了能够通过SSL使用SSL邮件网关和外部JSON API进行证书身份验证,已完成以下配置:

  • 我们创建了一个Java密钥库文件,其中包含SMTP邮件网关的证书链和外部JSON API的证书链
  • 我们将此密钥库文件配置为[TOMCAT]/bin/setenv.sh脚本中的Java启动参数,如下所示:
  • (我们需要使用证书存储文件作为密钥存储和信任存储,因为我们需要能够建立到外部SMTP邮件网关的SSL连接,并且extrenal JSON API和JSON API需要通过SSL证书进行身份验证。因此,我们的应用程序也需要提供有效的证书)

    现在问题来了!如果我们在上安装了描述的SSL配置,则无法通过SSL连接到MySQL数据库。只有此JDBC URL有效:

    jdbc.default.url=jdbc:mysql://[MYSQL_IP]:3306/lportal?characterEncoding=UTF-8&dontTrackOpenResources=true&holdResultsOpenOverStatementClose=true&useFastDateParsing=false&useUnicode=true&sslMode=DISABLED
    
    如果我们从setenv.sh中删除-Djavax.net.ssl.*参数,我们可以通过ssl连接到数据库,如下所示:

    jdbc.default.url=jdbc:mysql://[MYSQL_IP]:3306/lportal?characterEncoding=UTF-8&dontTrackOpenResources=true&holdResultsOpenOverStatementClose=true&useFastDateParsing=false&useUnicode=true&sslMode=REQUIRED&enabledTLSProtocols=TLSv1.2
    
    jdbc.default.driverClassName=com.mysql.cj.jdbc.Driver
    jdbc.default.url=jdbc:mysql://10.0.0.1:3306/lportal?characterEncoding=UTF-8&dontTrackOpenResources=true&holdResultsOpenOverStatementClose=true&useFastDateParsing=false&useUnicode=true&sslMode=DISABLED
    jdbc.default.username=mysqluser
    jdbc.default.password=PASSW0RD
    
    是的,我们还尝试将托管MySQL数据库中的ca-bundle.pem放入我们的证书存储

    每隔一次配置会导致:

    com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure__The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 
    

    因此,只有在不将-Djavax.net.SSL.*参数放入setenv.sh中的情况下,JDBC上的SSL才能工作。即使托管MySQL数据库中的ca-bundle.pem位于同一密钥库/信任库中,那么JDBC上的SSL也无法工作!曾经我已经试了很多让它运行,但它就是不起作用。我还使用了不同的MySQL Connector/J驱动程序版本

    有没有可能让JDBCURL完全忽略setenv.sh中的-Djavax.net.ssl.*参数

    还是有其他方法可以通过SSL将SMTP、SSL上的API和SSL上的JDBC集于一身?但是,所有接口都使用不同的证书链


    提前谢谢你

    我找到了问题的答案!解决方案是将JDBCSQL连接配置移动到JNDI数据源中

    在上述配置中,JDBC配置位于Java.properties配置文件中,如下所示:

    jdbc.default.url=jdbc:mysql://[MYSQL_IP]:3306/lportal?characterEncoding=UTF-8&dontTrackOpenResources=true&holdResultsOpenOverStatementClose=true&useFastDateParsing=false&useUnicode=true&sslMode=REQUIRED&enabledTLSProtocols=TLSv1.2
    
    jdbc.default.driverClassName=com.mysql.cj.jdbc.Driver
    jdbc.default.url=jdbc:mysql://10.0.0.1:3306/lportal?characterEncoding=UTF-8&dontTrackOpenResources=true&holdResultsOpenOverStatementClose=true&useFastDateParsing=false&useUnicode=true&sslMode=DISABLED
    jdbc.default.username=mysqluser
    jdbc.default.password=PASSW0RD
    
    现在,我已将JDBC配置移动到Tomcat JNDI数据源中,因此,我现在没有显示JDBC属性,而只显示了这一行:

    jdbc.default.jndi.name=jdbc/LiferayPool
    
    在[TOMCAT_HOME]/conf/context.xml中,我添加了这一行:

    <Context>
    ...
        <ResourceLink name="jdbc/LiferayPool" global="jdbc/LiferayPool" type="javax.sql.DataSource"/>
    
    ...
    </Context>
    

    我希望这能帮助有同样问题的人…

    使用
    javax.net.ssl.*
    参数来配置默认值。您应该修改应用程序,以便为JDBC和邮件使用不同的上下文。
      <GlobalNamingResources>
    ...
        <Resource name="jdbc/LiferayPool"
                   auth="Container"
                   description="Portal DB Connection"
                   type="javax.sql.DataSource"
                   factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
                   driverClassName="com.mysql.cj.jdbc.Driver"
    url="jdbc:mysql://10.0.0.1:3306/lportal?characterEncoding=UTF-8&amp;dontTrackOpenResources=true&amp;holdResultsOpenOverStatementClose=true&amp;useFastDateParsing=false&amp;useUnicode=true&amp;sslMode=VERIFY_CA&amp;clientCertificateKeyStoreUrl=file:///path/to/my.keystore&amp;clientCertificateKeyStorePassword=PASSW0RD&amp;clientCertificateKeyStoreType=PKCS12&amp;trustCertificateKeyStoreUrl=file:///path/to/my.keystore&amp;trustCertificateKeyStorePassword=PASSW0RD&amp;trustCertificateKeyStoreType=PKCS12&amp;enabledTLSProtocols=TLSv1.2&amp;autoReconnect=true"
                   username="mysqluser"
                   password="PASSW0RD"
                   maxActive="20"
                   maxIdle="5"
                   maxWait="10000" />
    
      </GlobalNamingResources>
    
    mysql> SELECT sbt.variable_value AS tls_version,  t2.variable_value AS cipher,                processlist_user AS user, processlist_host AS host         FROM performance_schema.status_by_thread  AS sbt         JOIN performance_schema.threads AS t ON t.thread_id = sbt.thread_id         JOIN performance_schema.status_by_thread AS t2 ON t2.thread_id = t.thread_id        WHERE sbt.variable_name = 'Ssl_version' and t2.variable_name = 'Ssl_cipher' ORDER BY tls_version, 4;
    +-------------+-----------------------------+--------------+--------------+
    | tls_version | cipher                      | user         | host         |
    +-------------+-----------------------------+--------------+--------------+
    | TLSv1.2     | ECDHE-RSA-AES256-GCM-SHA384 | mysqluser    | 10.0.0.101   |