是否可以通过编程方式向Connector/J提供Java KeyStore和TrustStore



我想使用Connector/J(或其他兼容的驱动程序(连接到MySQL/MariaDB RDBMS,并直接向驱动程序提供密钥库和信任库,而不是为磁盘上的密钥库/信任库提供文件名。

我不再将密钥和证书存储在磁盘上,我希望避免为了这个目的而将它们放入临时文件中。

这个答案似乎是。因为配置KeyStore和TrustStore的方法是提供URL,而不是类/工厂。

我认为是可能的,如果你愿意经历一系列的困难来实现它。

因为例如clientCertificateKeyStoreUrl将接受URL,所以您可以为其提供自定义协议处理程序,如mykeysupplier://mykey

您可以为mekeysupplier编写一个自定义的URLConnection类,然后从getInputStream()方法返回您想要的任何字节。你必须注册一个协议处理程序和类似的东西。

所以,这有点可怕的丑陋,但我认为它可以发挥作用,并且肯定会尝试至少一个这种想法的PoC,因为它可能会解决我的问题(我发布了最初的问题(。

可能还有其他选项。

我重新阅读了Connector/J的配置参考,有一个URL属性可以为连接指定:socketFactory。这必须是实现连接器/J接口SocketFactory的类的完全限定名称(请注意,这与标准库类javax.net.SocketFactory相似但无关(。

这个接口很小:

public interface SocketFaactory {
Socket afterHandshake() throws SocketException, IOException;
Socket beforeHandshake() throws SocketException, IOException;
Socket connect(String host, int portNumber, Properties props) throws SocketException, IOException;
}

稍后版本的驱动程序将第四个int loginTimeout参数添加到connect方法中。

无论如何,看起来这可能是解决方案的基础。

不幸的是,MySQL不使用普通的TLS连接,因此它可能不像从标准定制的javax.net.ssl.SSLSocketFactory返回Socket那么简单。

更新

SSL/TLS的魔力发生在连接之后,这是由于MySQL管理其协议的方式(它不仅仅是普通的TLS(。

在5.1-era驱动程序中,它是在一个名为ExportControlled的类中,在一个称为getSSLSocketFactoryDefaultOrConfigured的方法中完成的。在以后的版本中(我面前有8.0-era源代码(,它是在同一个类中完成的,但使用一个不同的方法performTlsHandshake

在没有对驱动程序源代码进行重大黑客攻击或重新实现大量代码的情况下,我怀疑更好的解决方案是从这个答案中实现基于URL的密钥库加载。

是的,可以通过编程向Connector/J提供Java KeyStore和TrustStore。您可以使用java.security.KeyStorejava.security.TrustStore类在内存中创建密钥库和信任库,然后分别通过javax.net.ssl.keyStorejavax.net.ssl.trustStore系统属性将它们传递给Connector/JDriverConnection类。这是的代码示例

import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
// ...
// Load the keystore and truststore data into memory
byte[] keystoreData = ...;
byte[] truststoreData = ...;
// Create the keystore and truststore objects
KeyStore keyStore = KeyStore.getInstance("JKS");
KeyStore trustStore = KeyStore.getInstance("JKS");
keyStore.load(new ByteArrayInputStream(keystoreData), keystorePassword);
trustStore.load(new ByteArrayInputStream(truststoreData), truststorePassword);
// Set the system properties to use the in-memory keystore and truststore
System.setProperty("javax.net.ssl.keyStore", keyStore);
System.setProperty("javax.net.ssl.trustStore", trustStore);
// Connect to the database using Connector/J
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);

最新更新