具有指定证书的Java MySQL SSL连接

具有指定证书的Java MySQL SSL连接,java,mysql,ssl,jdbc,mariadb,Java,Mysql,Ssl,Jdbc,Mariadb,我正在尝试制作一个Java应用程序,它使用jdbc(连接器/J)通过SSL加密连接到mariadb数据库。 我已经创建了一个自签名证书,并配置了服务器来使用它。 当我尝试连接时,我得到一个异常,因为证书是自签名的,并且没有添加到Java信任存储中,所以它不受信任。 因为我想修改信任库或为我的应用程序使用不同的信任库,所以我搜索了一种只告诉jdbc哪个证书受信任的方法,并找到了“直接提供证书” 当我现在尝试连接到: DriverManager.getConnection("jdbc:mysql:/

我正在尝试制作一个Java应用程序,它使用jdbc(连接器/J)通过SSL加密连接到mariadb数据库。 我已经创建了一个自签名证书,并配置了服务器来使用它。 当我尝试连接时,我得到一个异常,因为证书是自签名的,并且没有添加到Java信任存储中,所以它不受信任。 因为我想修改信任库或为我的应用程序使用不同的信任库,所以我搜索了一种只告诉jdbc哪个证书受信任的方法,并找到了“直接提供证书”

当我现在尝试连接到:

DriverManager.getConnection("jdbc:mysql://<hostname>:3306/<database>?useSSL=true&requireSSL=true&serverSslCert=/tmp/ssl/server-cert.pem", "<username>", "<password>");
DriverManager.getConnection(“jdbc:mysql://:3306/?useSSL=true&requireSSL=true&serverSslCert=/tmp/ssl/server-cert.pem”,“”,“”,“”);
在不再使用serverSslCert参数之前,我已获得此异常:

Exception in thread "main" 

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 136 milliseconds ago.  The last packet sent successfully to the server was 129 milliseconds ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:203)
    at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4901)
    at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2188)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2219)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2014)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:776)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:386)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)
    at gymcash.server.mysql.DriverWrapper.connect(DriverWrapper.java:22)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at gymcash.server.mysql.MySQL.connect(MySQL.java:48)
    at gymcash.server.mysql.MySQL.connect(MySQL.java:52)
    at gymcash.server.main.Main.main(Main.java:25)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:188)
    ... 21 more
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:304)
    at 

sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:992)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
    ... 29 more
Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:154)
    at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:80)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)
    at com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:297)
    ... 31 more
线程“main”中出现异常 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链路故障 从服务器成功接收的最后一个数据包是136毫秒前。成功发送到服务器的最后一个数据包是129毫秒前。 位于sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) 位于sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 位于java.lang.reflect.Constructor.newInstance(Constructor.java:423) 位于com.mysql.jdbc.Util.HandleneInstance(Util.java:425) 位于com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990) 位于com.mysql.jdbc.ExportControlled.transformsockettosslssocket(ExportControlled.java:203) 位于com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4901) 在com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659)上 位于com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226) 位于com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2188) 位于com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2219) com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2014) 位于com.mysql.jdbc.ConnectionImpl(ConnectionImpl.java:776) 位于com.mysql.jdbc.JDBC4Connection(JDBC4Connection.java:47) 位于sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) 位于sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 位于java.lang.reflect.Constructor.newInstance(Constructor.java:423) 位于com.mysql.jdbc.Util.HandleneInstance(Util.java:425) 位于com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:386) 位于com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330) 位于gymcash.server.mysql.DriverWrapper.connect(DriverWrapper.java:22) 位于java.sql.DriverManager.getConnection(DriverManager.java:664) 位于java.sql.DriverManager.getConnection(DriverManager.java:247) 位于gymcash.server.mysql.mysql.connect(mysql.java:48) 位于gymcash.server.mysql.mysql.connect(mysql.java:52) 位于gymcash.server.main.main.main(main.java:25) 原因:javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:java.security.cert.CertPathValidatorException:路径未与任何信任锚链接 位于sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 位于sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964) 位于sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328) 位于sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322) 位于sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614) 位于sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) 位于sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052) 位于sun.security.ssl.Handshaker.process_记录(Handshaker.java:987) 位于sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072) 位于sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) 位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413) 位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397) 位于com.mysql.jdbc.ExportControlled.transformsockettosslssocket(ExportControlled.java:188) ... 还有21个 原因:java.security.cert.CertificateException:java.security.cert.CertPathValidator异常:路径未与任何信任锚链接 位于com.mysql.jdbc.ExportControlled$X509TrustManagerRapper.checkServerTrusted(ExportControlled.java:304) 在 sun.security.ssl.AbstractTrustManagerRapper.checkServerTrusted(SSLContextImpl.java:992) 位于sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596) ... 还有29个 原因:java.security.cert.CertPathValidator异常:路径未与任何信任锚链接 位于sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:154) 位于sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:80) 位于java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) 位于com.mysql.jdbc.ExportControlled$X509TrustManagerRapper.checkServerTrusted(ExportControlled.java:297) ... 还有31个 我不明白我做错了什么,因为文件存在,路径是绝对的,并且与服务器使用的路径相同。有人能告诉我我做错了什么吗


我正在使用Java 8,mysql-connector-Java-5.1.45

有几种方法可以做到这一点。您可以将自签名证书或用于签名证书的证书颁发机构放入用于连接的JVM使用的默认java密钥存储。您需要使用Keytool来完成此操作。但是,除非您管理一个企业VM包,否则您可能不想劫持默认值
if (DB_SSL || SSL) {
            System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
            System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASS);
            System.setProperty("javax.net.ssl.trustStore", KEYSTORE);
            System.setProperty("javax.net.ssl.trustStorePassword", KEYSTORE_PASS);
        if (DEBUG_OPTION) {
            System.setProperty("javax.net.debug", "true");
        }
    }

private static String KEYSTORE = "/home/me/.keystore";
private static String KEYSTORE_PASS = "changeit";