使用Java与MySQL服务器建立SSL连接
我正在尝试使用Java over SSL连接到MySQL服务器。 我收到以下exception:
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 (ie 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.(ConnectionImpl.java:827) at com.mysql.jdbc.JDBC4Connection.(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.(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
(您可能必须将“ca.pem”文件的名称更改为您自己的CA证书文件名)
请记住保持
您需要输入JVM信任库的密码:此密码始终为“changeit”。
我不能保证这会解决问题,但这是我在做这个工作时迈出的重要一步,最后我得到了它。
- 如何将wsdl中定义的Soap Header添加到CXF中的Web服务客户端?
- 无法通过JRXmlLoader加载位于jar文件中的jrxml:获取java.io.FileNotFoundException
- 如何从我的wav文件中绘制声音数据?
- 让JSF从EL而不是bean字段访问Map 值?
- Drools KnowledgeBase已弃用
- 这是Double Check Locking的更好版本,没有易失性和同步开销
- 错误的值类:类org.apache.hadoop.io.Text不是类org.apache.hadoop.io.IntWritable
- 创建无界和有界外卡类型数组之间的区别?
- 在Java中捕获nullpointerexception