
# 通过JDBC连接TaurusDB实例
通过JDBC连接实例的方式有无需下载SSL证书连接和用户下载SSL证书连接两种，其中使用SSL证书连接通过了加密功能，具有更高的安全性。TaurusDB新实例默认开启SSL数据加密，SSL连接实现了数据加密功能，但同时会增加网络连接响应时间和CPU消耗，请评估对业务的性能影响，根据需要进行设置，详细内容请参考[设置SSL数据加密](https://support.huaweicloud.com/usermanual-taurusdb/taurusdb_03_0142.html)。
#### 前提条件
用户需要具备以下技能：
- 熟悉计算机基础知识。
- 了解java编程语言。
- 了解JDBC基础知识。
 
#### 通过JDBC连接实例
- [使用SSL证书连接]
  使用SSL证书连接实例，即通过证书校验并连接数据库。
  ![](https://support.huaweicloud.com/usermanual-taurusdb/public_sys-resources/caution_3.0-zh-cn.png)
  以下提供的方式不适用于数据库用户的ssl_type为x509的认证方式。
  执行命令，查看当前用户的ssl_type值。
  ```
  select ssl_type from mysql.user where user = 'xxx';
  ```
  1. 下载CA证书或捆绑包。
     
     1. 在"实例管理"页面，单击实例名称，进入实例概览页面。
     
     2. 单击"SSL"开关右侧的"下载"。
     
     
     
     
  
  2. 使用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\\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_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
     ```
     
     
  
  3. 通过JDBC连接TaurusDB数据库，代码中的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"，即读写公网地址。您可以在该实例概览页面的"网络信息"区域查看。  - 如果开启了数据库代理，通过数据库代理连接TaurusDB实例时，此处的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 |
        
     代码示例（连接TaurusDB数据库的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 .... 
             } 
         } 
     }
     ```
     
     
   
- [无证书连接]
  ![](https://support.huaweicloud.com/usermanual-taurusdb/public_sys-resources/note_3.0-zh-cn.png)
  该方式不对服务端进行证书校验，用户无需下载SSL证书。
  1. 通过JDBC连接TaurusDB数据库实例，代码中的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。                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
        
     代码示例（连接TaurusDB数据库的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://<instance_ip>:<instance_port>/<database_name>?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证书模式连接TaurusDB时，报如下类似错误：
  ```
  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-java-8.0.17.jar:8.0.17]
      at
  com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.
  java:99) ~[mysql-connector-java-8.0.17.jar:8.0.17]
      at
  com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:331) ~
  [mysql-connector-java-8.0.17.jar:8.0.17]
  ... 68 common frames omitted
  ```
  
- 解决方法 您可以在[3]中的代码链路中，根据客户端使用的Jar包指定对应参数值进行连接。示例如下：
  - mysql-connector-java-5.1.*xx* .jar（对于8.0.28以前版本的连接驱动，使用enabledTLSProtocols参数，详情请参考[官方文档](https://dev.mysql.com/doc/connector-j/en/connector-j-reference-using-ssl.html)。）
    ```
    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.28及以后版本的连接驱动，使用tlsVersions参数）
    ```
    jdbc:mysql://instance_ip:instance_port/database_name? 
     requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file: 
     truststore_file&trustCertificateKeyStorePassword=password& tlsVersions =TLSv1.2
    ```
    
   
 
