通过JDBC连接实例的方式有无需下载SSL证书连接和用户下载SSL证书连接两种,其中使用SSL证书连接通过了加密功能,具有更高的安全性。RDS for MySQL新实例默认关闭SSL数据加密,开启SSL请参考设置SSL数据加密。SSL连接实现了数据加密功能,但同时也会增加网络连接响应时间和CPU消耗,不建议开启SSL数据加密。
前提条件
用户需要具备以下技能:
熟悉计算机基础知识。
了解java编程语言。
了解JDBC基础知识。
使用SSL证书连接
说明
使用SSL证书连接实例,即通过证书校验并连接数据库。RDS for MySQL实例不支持X509认证方式。
步骤 1 下载CA证书或捆绑包。
1. 在“实例管理”页面,单击实例名称进入“基本信息”页面。
2. 单击“SSL”处的“下载”。
步骤 2 使用keytool工具通过CA证书生成truststore文件。
<keytool工具的安装路径> ./keytool.exe -importcert -alias <MySQLCACert> -file <ca.pem> -keystore <truststore_file> -storepass <password>
表 变量说明
变量 | 说明 |
---|---|
<keytool工具的安装路径> | 请替换为JDK或JRE安装路径的bin目录,例如C:\Program Files (x86)\Java\jdk11.0.7\bin。 |
<MySQLCACert> | 请设置truststore文件的名称。建议设置为具有业务意义的名称,便于后续识别。 |
<ca.pem> | 请替换为步骤1中下载解压后CA证书的名称,例如ca.pem。 |
<truststore_file> | 请设置truststore文件的存放路径。 |
<password> | 请设置truststore文件的密码。 |
代码示例(使用JDK安装路径下的keytool工具生成truststore文件):
Owner: CN=MySQL_Server_5.7.17_Auto_Generated_CA_Certificate
Issuer: CN=MySQL_Server_5.7.17_Auto_Generated_CA_Certificate
Serial number: 1
Valid from: Thu Feb 16 11:42:43 EST 2017 until: Sun Feb 14 11:42:43 EST 2027
Certificate fingerprints:
MD5: 18:87:97:37:EA:CB:0B:5A:24:AB:27:76:45:A4:78:C1
SHA1: 2B:0D:D9:69:2C:99:BF:1E:2A:25:4E:8D:2D:38:B8:70:66:47:FA:ED
SHA256:C3:29:67:1B:E5:37:06:F7:A9:93:DF:C7:B3:27:5E:09:C7:FD:EE:2D:18:86:F4:9C:40:D8:26:CB:DA:95: A0:24
Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key
Version: 1
Trust this certificate? [no]: y
Certificate was added to keystore
步骤 3 通过JDBC连接MySQL数据库,代码中的JDBC连接格式如下:
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?param1=value1¶m2=value2
表 参数说明
参数 | 说明 |
---|---|
<instance_ip> | 请替换为实例的IP地址。 说明
|
<instance_port> | 请替换为实例的数据库端口,默认为3306。 说明 您可以在该实例的“连接管理”页面查看。 |
<database_name> | 请替换为连接实例使用的数据库名,默认为mysql。 |
<param1> | requireSSL,用于设置服务端是否支持SSL连接。取值如下:
说明 requireSSL与其他连接参数、sslMode之间的关系请参考表 连接参数与SSLMode的关系说明。 |
<param2> | useSSL,用于设置客户端是否使用SSL连接服务端。取值如下:
说明 useSSL与其他连接参数、sslMode之间的关系请参考表 连接参数与SSLMode的关系说明。 |
<param3> | verifyServerCertificate,客户端是否校验服务端的证书。取值如下:
说明 verifyServerCertificate与其他连接参数、sslMode之间的关系请参考表 连接参数与SSLMode的关系说明。 |
<param4> | trustCertificateKeyStoreUrl,取值为file:<truststore_file>。 <truststore_file>请替换为步骤2中truststore文件设置的存储路径。 |
<param5> | trustCertificateKeyStorePassword,取值为步骤2中truststore文件设置的密码。 |
表 连接参数与SSLMode的关系说明
useSSL | requireSSL | verifyServerCertificate | sslMode |
---|---|---|---|
false | 不涉及 | 不涉及 | DISABLED |
true | false | false | PREFERRED |
true | true | false | REQUIRED |
true | 不涉及 | true | VERIFY_CA |
代码示例(连接MySQL数据库的java代码):
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。
// 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
public class JDBCTest {
String USER = System.getenv("EXAMPLE_USERNAME_ENV");
String PASS = System.getenv("EXAMPLE_PASSWORD_ENV");
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
// url中所需的连接参数根据实际情况配置
String url = "jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?param1=value1¶m2=value2";
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url, USER, PASS);
stmt = conn.createStatement();
String sql = "show status like 'ssl%'";
ResultSet rs = stmt.executeQuery(sql);
int columns = rs.getMetaData().getColumnCount();
for (int i = 1; i <= columns; i++) {
System.out.print(rs.getMetaData().getColumnName(i));
System.out.print("\t");
}
while (rs.next()) {
System.out.println();
for (int i = 1; i <= columns; i++) {
System.out.print(rs.getObject(i));
System.out.print("\t");
}
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// release resource ....
}
}
}
----结束
无证书连接
说明
该方式不对服务端进行证书校验,用户无需下载SSL证书。
步骤 1 通过JDBC连接RDS for MySQL数据库实例,代码中的JDBC连接格式如下:
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?useSSL=false
表 变量说明
变量 | 说明 |
---|---|
<instance_ip> | 请替换为实例的IP地址。 说明
|
<instance_port> | 请替换为实例的数据库端口,默认为3306。 说明 您可以在该实例的“连接管理”页面查看。 |
<database_name> | 请替换为连接实例使用的数据库名,默认为mysql。 |
代码示例(连接MySQL数据库的java代码):
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。
// 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV。
public class MyConnTest {
final public static void main(String[] args) {
Connection conn = null;
// url中所需的连接参数根据实际情况配置
String url = "jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?param1=value1¶m2=value2";
String USER = System.getenv("EXAMPLE_USERNAME_ENV");
String PASS = System.getenv("EXAMPLE_PASSWORD_ENV");
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url,USER,PASS);
System.out.println("Database connected");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500");
while (rs.next()) {
System.out.println(rs.getString(1));
}
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Test failed");
} finally {
// release resource ....
}
}
}
----结束
相关问题
问题描述
当您使用8.0及以上版本的JDK通过SSL证书模式连接MySQL时,报如下类似错误:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or
cipher suites are inappropriate)
at sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:171) ~[na:1.8.0_292]
at sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98) ~
[na:1.8.0_292]
at sun.security.ssl.TransportContext.kickstart(TransportContext.java:220) ~
[na:1.8.0_292]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:428) ~
[na:1.8.0_292]
at
com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:316) ~
[mysql-connector-java-8.0.17.jar:8.0.17]
at
com.mysql.cj.protocol.StandardSocketFactory.performTlsHandshake(StandardSocketFactory.java
:188) ~[mysql-connector-java8.0.17.jar:8.0.17]
at
com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.
java:99) ~[mysql-connector-java8.0.17.jar:8.0.17]
at
com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:331) ~
[mysql-connector-java8.0.17.jar:8.0.17]
... 68 common frames omitted
解决方法
您可以在步骤3中的代码链路中,根据客户端使用的Jar包指定对应参数值进行连接。示例如下:
− mysql-connector-java-5.1.xx.jar(对于8.0.18及以前版本的连接驱动,使用enabledTLSProtocols参数,详见官方文档)
在数据库连接url:jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?param1=value1¶m2=value2 的末尾以param1=value1的形式增加enabledTLSProtocols=TLSv1.2
− mysql-connector-java-8.0.xx.jar(对于8.0.18以后版本的连接驱动,使用tlsVersions参数)
在数据库连接url:jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?param1=value1¶m2=value2 的末尾以param1=value1的形式增加tlsVersions=TLSv1.2