通過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\jdk-11.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