簡體   English   中英

使用Java與MySQL服務器的SSL連接

[英]SSL connection to MySQL server with Java

我正在嘗試使用Java over SSL連接到MySQL服務器。 我收到以下異常:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Cannot connect to MySQL server on www.mysite.com:3306.

Make sure that there is a MySQL server running on the machine/port you are trying to connect to and that the machine this software is running on is able to connect to this host/port (i.e. not firewalled). Also make sure that the server has not been started with the --skip-networking flag.

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
at com.mysql.jdbc.Util.getInstance(Util.java:382)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:827)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:378)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Caused by: java.lang.UnsupportedOperationException: The method shutdownInput() is not supported in SSLSocket
at sun.security.ssl.BaseSSLSocketImpl.shutdownInput(Unknown Source)
at com.mysql.jdbc.MysqlIO.forceClose(MysqlIO.java:506)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2404)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2163)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794)
... 25 more

這是我的代碼:

properties = new Properties();
properties.put("user", "myuser");
properties.put("password", "mypassword");
properties.put("useSSL", "true");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "keystorepass");
System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "truststorepass");
connection = DriverManager.getConnection("jdbc:mysql://www.mysite.com:3306/mydatabase", properties);

細節

密鑰庫和信任庫創建

我生成了密鑰庫和信任庫,如下所示:

openssl pkcs12 -export -inkey client-key.pem -in client-cert.pem > keystore.p12
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jks -deststoretype JKS

openssl x509 -outform der -in ca.pem -out ca.der
keytool -import -file ca.der -alias myCA -keystore truststore.jks

原始證書

這是我的證書清單:

  • ca.pem
  • 客戶key.pem
  • 客戶cert.pem
  • 服務器key.pem
  • 服務器cert.pem

無SSL連接

以下代碼工作正常,只是為了演示我可以用Java連接到MySQL服務器:

properties = new Properties();
properties.put("user", "myuser");
properties.put("password", "mypassword");
connection = DriverManager.getConnection("jdbc:mysql://www.mysite.com:3306/mydatabase", properties);

在命令行上使用MySQL時,SSL上的連接有效

我使用以下命令啟動MySQL服務器:

mysqld --ssl-ca=ca.pem --ssl-cert=server-cert.pem --ssl-key=server-key.pem

然后我使用MySQL命令連接到它:

mysql --host=www.mysite.com --user=myuser --password=mypassword --database=mydatabase --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem

這工作,並在查詢SHOW STATUS LIKE 'Ssl_cipher'得到正確的結果:

+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA |
+---------------+--------------------+

如果您遇到此問題,請至少確保將CA證書導入JRE的密鑰庫!

keytool -import -noprompt -trustcacerts -alias <uniqueCAAlias> -file ca.pem -keystore <pathtocacerts>

(您可能必須將“ca.pem”文件的名稱更改為您自己的CA證書文件名)

請記住保持<uniqueCAAlias>獨特的東西。 此外,更改<pathtocacerts>以使其與JVM的路徑匹配。 請注意,這很可能是最高版本的JRE,但它也可能是SDK的JRE或安裝的不同JRE(如“C:\\ Program Files \\ Java \\ jre1.8.0_25 \\ lib \\ security \\ cacerts”) )

您需要輸入JVM信任庫的密碼:此密碼始終為“changeit”。

我不能保證這會解決問題,但這是我在做這個工作時邁出的重要一步,我最終得到了它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM