MySQL JDBC over SSL 问题

Posted

技术标签:

【中文标题】MySQL JDBC over SSL 问题【英文标题】:MySQL JDBC over SSL problem 【发布时间】:2011-06-07 11:26:59 【问题描述】:

如何使 mysql JDBC 在 SSL 上工作(使用 X509 证书验证)?

我有 MySQL 手册中所述的自行创建的证书,在 Using SSL for Secure Connections 中,具体来说:

# Create CA certificate
shell> openssl genrsa 2048 > ca-key.pem
shell> openssl req -new -x509 -nodes -days 1000 \
         -key ca-key.pem > ca-cert.pem

# Create server certificate
shell> openssl req -newkey rsa:2048 -days 1000 \
         -nodes -keyout server-key.pem > server-req.pem
shell> openssl x509 -req -in server-req.pem -days 1000 \
         -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem

# Create client certificate
shell> openssl req -newkey rsa:2048 -days 1000 \
         -nodes -keyout client-key.pem > client-req.pem
shell> openssl x509 -req -in client-req.pem -days 1000 \
         -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem

发出GRANT ALL ON *.* TO vic@localhost IDENTIFIED BY '12345' REQUIRE X509; 后,我可以通过命令行连接到 MySQL:

mysql -u vic -p --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem mysql
...

mysql>  SHOW STATUS LIKE 'Ssl_cipher';
+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA |
+---------------+--------------------+

但是,当我尝试运行 Java 测试时,我得到验证失败:Access denied for user 'vic'@'localhost' (using password: YES)。代码如下:

public class Launcher 
    public static void main(String[] args) throws DbException, SQLException, ClassNotFoundException 
        StringBuffer sb = new StringBuffer("jdbc:mysql://localhost/bt?useSSL=true&");
        sb.append("user=vic&password=12345&");
        sb.append("clientCertificateKeyStorePassword=123456&");
        sb.append("clientCertificateKeyStoreType=JKS&");
        sb.append("clientCertificateKeyStoreUrl=file:///home/vic/tmp/client-keystore&");
        sb.append("trustCertificateKeyStorePassword=123456&");
        sb.append("trustCertificateKeyStoreType=JKS&");
        sb.append("trustCertificateKeyStoreUrl=file:///home/vic/tmp/ca-keystore");

        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection(sb.toString());

        Statement st = c.createStatement();
        ResultSet rs = st.executeQuery("SELECT * FROM test_table");
        while (rs.next()) 
            System.out.println(rs.getInt("id"));
        
        rs.close(); st.close(); c.close();
    

以下是我准备 Java 密钥库文件的方法:

keytool -import -alias mysqlServerCACert -file ca-cert.pem -keystore ca-keystore
keytool -import -file client-cert.pem -keystore client-keystore -alias client-key

更新如果我使用“root”用户而不是“vic”,我可以通过 JDBC 通过 SSL 进行连接。然后下面的代码

    Statement st = c.createStatement();
    ResultSet rs = st.executeQuery("SHOW STATUS LIKE 'Ssl_cipher';");
    while (rs.next()) 
        System.out.println(rs.getString(1));
        System.out.println(rs.getString(2));
    

打印

Ssl_cipher
DHE-RSA-AES128-SHA

但是我不能在生产中使用 root,我想知道为什么 JDBC 使用 AES128,而命令行 mysql 客户端使用 AES256。

UPDATE2 在我将user 表中root@localhostssl_type 更改为X509 后,请求客户端的完整身份验证,我得到的root 行为与vic 相同——可以'不通过 JDBC 登录。

UPDATE3 如果我在GRANT 语句中使用REQUIRE SSL 而不是REQUIRE X509,则代码有效。是否可以让 X509 工作?

【问题讨论】:

见***.com/questions/11509751/… 【参考方案1】:

最近向 MariaDB JDBC 驱动程序(也适用于连接 MySQL)添加了对自签名证书的支持。最新版本(撰写本文时为 1.1.3)还允许您在运行时直接指定服务器证书,这样您就无需提前配置密钥存储或导入证书。

要设置的两个属性是useSSLserverSslCert。后者可以是证书本身(字符串值)或包含证书的文件的路径(完整路径或类路径相对):

String url = "jdbc:mysql://" + host + ":" + port + "/" + database;
Properties info = new Properties();
info.setProperty("user", username);
info.setProperty("password", password);
info.setProperty("useSSL", "true");
info.setProperty("serverSslCert", "classpath:server.crt");
Connection conn = DriverManager.getConnection(url, info);

有关如何连接的完整工作示例,请参见此处:https://github.com/properssl/java-jdbc-mariadb

【讨论】:

【参考方案2】:

我已决定使用REQUIRE SSL。如果有人知道如何使 X509 与 JDBC 一起工作,我们将不胜感激。

【讨论】:

查看我的回答,了解如何将自签名 X.509 证书与 MySQL/MariaDB JDBC 连接一起使用。【参考方案3】:

当用户仅配置了 REQUIRES SSL 时,我什至无需指定客户端证书属性即可连接。

【讨论】:

【参考方案4】:

似乎 MariaDB 驱动程序人员有一个测试类,可以遍历所有场景,包括“REQUIRES X509”。

https://github.com/MariaDB/mariadb-connector-j/blob/master/src/test/java/org/mariadb/jdbc/SslTest.java

【讨论】:

以上是关于MySQL JDBC over SSL 问题的主要内容,如果未能解决你的问题,请参考以下文章

MariaDB over SSL 不工作,“证书验证失败”

与 SSL 的 mysql jdbc 连接在 tls 握手级别失败

mysql使用jdbc连接增加ssl认证

在 context.xml 中指定用于 jdbc 的 SSL

Tomcat JDBC 认证 MySQL SSL加密

如何使用SSL JDBC连接到MySQL服务器