通过JDBC连接GaussDB(for MySQL)实例
通过JDBC连接实例的方式有无需下载SSL证书连接和用户下载SSL证书连接两种,其中使用SSL证书连接通过了加密功能,具有更高的安全性。GaussDB(for MySQL)新实例默认开启SSL数据加密,SSL连接实现了数据加密功能,但同时会增加网络连接响应时间和CPU消耗,请评估对业务的性能影响,根据需要进行设置,详细内容请参考设置SSL数据加密。
前提条件
用户需要具备以下技能:
- 熟悉计算机基础知识。
- 了解java编程语言。
- 了解JDBC基础知识。
使用SSL证书连接
使用SSL证书连接实例,即通过证书校验并连接数据库。
以下提供的方式不适用于数据库用户的ssl_type为x509的认证方式。
执行命令查看当前用户的ssl_type值:
select ssl_type from mysql.user where user = 'xxx';
- 下载CA证书或捆绑包。
- 在“实例管理”页面,单击实例名称进入实例概览页面。
- 单击“SSL”开关右侧的“下载”。
- 使用keytool工具通过CA证书生成truststore文件。
<keytool工具的安装路径> ./keytool.exe -importcert -alias <MySQLCACert> -file <ca.pem> -keystore <truststore_file> -storepass <password>
表1 变量说明 变量
说明
<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_8.0.22_Auto_Generated_CA_Certificate Issuer: CN=MySQL_Server_8.0.22_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
- 通过JDBC连接GaussDB(for MySQL)数据库,代码中的JDBC链接格式如下:
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>? requireSSL=<value1>&useSSL=<value2>&verifyServerCertificate=<value3>&trustCertificateKeyStoreUrl=file: <truststore_file>&trustCertificateKeyStorePassword=<password>
表2 参数说明 参数
说明
<instance_ip>
请替换为实例的IP地址。
说明:- 如果通过弹性云服务器连接,“instance_ip”是实例的“读写内网地址”。您可以在该实例概览页面的“网络信息”区域查看。
- 如果通过公网连接,“instance_ip”为该实例已绑定的“弹性公网IP”,即读写公网地址。您可以在该实例概览页面的“网络信息”区域查看。
- 如果开启了数据库代理,通过数据库代理连接GaussDB(for MySQL)实例时,此处的IP为数据库代理地址。您可以在数据库代理页面查看代理地址。
<instance_port>
请替换为实例的数据库端口,默认为3306。
说明:您可以在该实例概览页面的“网络信息”区域查看。
<database_name>
请替换为连接实例使用的数据库名,默认为mysql。
<value1>
requireSSL的值,用于设置服务端是否支持SSL连接。取值如下:
- true:支持。
- false:不支持。
说明:requireSSL与其他连接参数、sslMode之间的关系请参考表3。
<value2>
useSSL的值,用于设置客户端是否使用SSL连接服务端。取值如下:
- true:使用。
- false:不使用。
说明:
useSSL与其他连接参数、sslMode之间的关系请参考表3。
<value3>
verifyServerCertificate的值,客户端是否校验服务端的证书。取值如下:
- true:校验。
- false:不校验。
说明:
verifyServerCertificate与其他连接参数、sslMode之间的关系请参考表3。
<truststore_file>
请替换为2中为truststore文件设置的存储路径。
<password>
请替换为2中为truststore文件设置的密码。
表3 连接参数与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; public class JDBCTest { // 认证使用用户名和密码直接写在代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。 // 本示例中以用户名和密码保存在环境变量中为例,运行本示例前请先在环境变量中设置环境变量EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV(环境变量名称请根据自身情况进行设置)。 static final String USER = System.getenv("EXAMPLE_USERNAME_ENV"); static final String PASS = System.getenv("EXAMPLE_PASSWORD_ENV"); public static void main(String[] args) { Connection conn = null; Statement stmt = null; String url = "jdbc:mysql://<instance_ip>:<instance_port>/<database_name>? requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file: <truststore_file>&trustCertificateKeyStorePassword=<password>"; 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证书。
- 通过JDBC连接GaussDB(for MySQL)数据库实例,代码中的JDBC链接格式如下:
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>?useSSL=false
表4 变量说明 变量
说明
<instance_ip>
请替换为实例的IP地址。
说明:- 如果通过弹性云服务器连接,“instance_ip”是实例的“读写内网地址”。您可以在该实例概览页面的“网络信息”区域查看。
- 如果通过公网连接,“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; public class MyConnTest { final public static void main(String[] args) { Connection conn = null; // set sslmode here. // no ssl certificate, so do not specify path. String url = "jdbc:mysql://192.168.0.225:3306/my_db_test?useSSL=false"; try { Class.forName("com.mysql.jdbc.Driver"); // 认证使用用户名和密码直接写在代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。 // 本示例中以用户名和密码保存在环境变量中为例,运行本示例前请先在环境变量中设置环境变量EXAMPLE_USERNAME_ENV和EXAMPLE_PASSWORD_ENV(环境变量名称请根据自身情况进行设置)。 conn = DriverManager.getConnection(url, System.getenv("EXAMPLE_USERNAME_ENV"), System.getenv("EXAMPLE_PASSWORD_ENV")); 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参数,详情请参考官方文档。)
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>? requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file: <truststore_file>&trustCertificateKeyStorePassword=<password>& enabledTLSProtocols=TLSv1.2
- mysql-connector-java-8.0.xx.jar(对于8.0.18以后版本的连接驱动,使用tlsVersions参数)
jdbc:mysql://<instance_ip>:<instance_port>/<database_name>? requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file: <truststore_file>&trustCertificateKeyStorePassword=<password>& tlsVersions =TLSv1.2
- mysql-connector-java-5.1.xx.jar(对于8.0.18及以前版本的连接驱动,使用enabledTLSProtocols参数,详情请参考官方文档。)