Java 禁用mySQL RDS客户端身份验证

Java 禁用mySQL RDS客户端身份验证,java,mysql,ssl,amazon-rds,mysql-connector,Java,Mysql,Ssl,Amazon Rds,Mysql Connector,我正在尝试从JavaSpringBoot应用程序连接到mySQL RDS数据库。我已对数据库进行了必要的更改 ALTER USER 'my_app'@'%' require SSL; GRANT USAGE ON *.* TO 'my_app'@'%' REQUIRE SSL; 但是,这种连接不会发生。 它在客户端身份验证部分失败。服务器(mysql db)无法对客户端(java应用程序)进行身份验证 问题: import java.sql.Connection; import java.sq

我正在尝试从JavaSpringBoot应用程序连接到mySQL RDS数据库。我已对数据库进行了必要的更改

ALTER USER 'my_app'@'%' require SSL;
GRANT USAGE ON *.* TO 'my_app'@'%' REQUIRE SSL;
但是,这种连接不会发生。 它在客户端身份验证部分失败。服务器(mysql db)无法对客户端(java应用程序)进行身份验证

问题:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

//1. Dowload my sql connector to a folder "jars". http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar
//   This file and the jars folder are on the same folder (or level). Not inside one another.
//2. edit this file to have your settings. Name of the DB,URL,username,password,trustStore,keyStore,DB name, table name.
//3. compile the file:  javac -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode.java
//4. run the program:   java -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode

public class SampleCode {
  public static void main(String[] args) {
    Connection con;
    try {
      // TODO: replace with your settings.
      System.setProperty("javax.net.ssl.trustStore", "path/resource/certs/trustStore.jks");
      System.setProperty("javax.net.ssl.trustStorePassword", "trustStore_pass");
      System.setProperty("javax.net.ssl.keyStore", "path/resource/certs/keyStore.jks");
      System.setProperty("javax.net.ssl.keyStorePassword", "keyStore_pass");
      System.setProperty("javax.net.debug", "ssl:handshake");

      Class.forName("com.mysql.cj.jdbc.Driver");
      // TODO: replace with your settings.
      con = DriverManager.getConnection(
          "jdbc:mysql://my_db_name.random_string.us-east-1.rds.amazonaws.com:3/my_db?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true",
          "my_app", "my_pass");

      System.out.println(" connection successful \n");
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM my_table "); // TODO: replace with yours.
      while (rs.next()) {
        System.out.println("id : " + rs.getString("id"));
      }

      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

  • 如何禁用客户端身份验证? 根据文档,除非您“需要X509”,否则应禁用该功能。所以,我对此感到困惑。我所指的文档如下:

  • 我如何使用密钥库和信任库实现这一点

更多信息:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

//1. Dowload my sql connector to a folder "jars". http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar
//   This file and the jars folder are on the same folder (or level). Not inside one another.
//2. edit this file to have your settings. Name of the DB,URL,username,password,trustStore,keyStore,DB name, table name.
//3. compile the file:  javac -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode.java
//4. run the program:   java -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode

public class SampleCode {
  public static void main(String[] args) {
    Connection con;
    try {
      // TODO: replace with your settings.
      System.setProperty("javax.net.ssl.trustStore", "path/resource/certs/trustStore.jks");
      System.setProperty("javax.net.ssl.trustStorePassword", "trustStore_pass");
      System.setProperty("javax.net.ssl.keyStore", "path/resource/certs/keyStore.jks");
      System.setProperty("javax.net.ssl.keyStorePassword", "keyStore_pass");
      System.setProperty("javax.net.debug", "ssl:handshake");

      Class.forName("com.mysql.cj.jdbc.Driver");
      // TODO: replace with your settings.
      con = DriverManager.getConnection(
          "jdbc:mysql://my_db_name.random_string.us-east-1.rds.amazonaws.com:3/my_db?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true",
          "my_app", "my_pass");

      System.out.println(" connection successful \n");
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM my_table "); // TODO: replace with yours.
      while (rs.next()) {
        System.out.println("id : " + rs.getString("id"));
      }

      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

我还将AWS根证书和区域证书导入到我的信任存储中。此时(没有作为JVM传递的密钥库),连接正常

但是,在我的应用程序中,我还需要使用密钥库

 -Djavax.net.ssl.keyStore=path/keyStore.jks
 -Djavax.net.ssl.keyStorePassword=<keyStore_password>
添加ssl握手调试时,我会看到以下日志:

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<Empty>
localhost-startStop-1, READ: TLSv1.1 Handshake, length = 4
*** ServerHelloDone
matching alias: mysqlrds
matching alias: client-nonprod
*** Certificate chain
chain [0] = [
参考资料:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

//1. Dowload my sql connector to a folder "jars". http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar
//   This file and the jars folder are on the same folder (or level). Not inside one another.
//2. edit this file to have your settings. Name of the DB,URL,username,password,trustStore,keyStore,DB name, table name.
//3. compile the file:  javac -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode.java
//4. run the program:   java -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode

public class SampleCode {
  public static void main(String[] args) {
    Connection con;
    try {
      // TODO: replace with your settings.
      System.setProperty("javax.net.ssl.trustStore", "path/resource/certs/trustStore.jks");
      System.setProperty("javax.net.ssl.trustStorePassword", "trustStore_pass");
      System.setProperty("javax.net.ssl.keyStore", "path/resource/certs/keyStore.jks");
      System.setProperty("javax.net.ssl.keyStorePassword", "keyStore_pass");
      System.setProperty("javax.net.debug", "ssl:handshake");

      Class.forName("com.mysql.cj.jdbc.Driver");
      // TODO: replace with your settings.
      con = DriverManager.getConnection(
          "jdbc:mysql://my_db_name.random_string.us-east-1.rds.amazonaws.com:3/my_db?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true",
          "my_app", "my_pass");

      System.out.println(" connection successful \n");
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM my_table "); // TODO: replace with yours.
      while (rs.next()) {
        System.out.println("id : " + rs.getString("id"));
      }

      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}


在使用hibernate的应用程序中,我遇到了同样的错误。显然,RDS只在SSL握手期间进行客户端身份验证。您可以通过连接属性覆盖用于jdbc连接的密钥存储,而不是因为需要为应用程序使用单独的密钥存储而禁用客户端身份验证

  • 按照“更新JDBC的应用程序信任存储”一节中提到的步骤获取将用于RDS连接的客户端密钥库
  • 在示例代码中添加以下代码:
  • 通过执行上述操作,您可以覆盖将用于建立到RDS的连接的密钥库,同时使用单独的系统范围密钥库。请注意,每次要连接到RDS实例时,都需要设置属性

    如中所述:

    请注意,当一起使用时,连接属性将覆盖由其他两个方法设置的值。此外,使用连接属性设置的任何值仅在该连接中使用,而使用系统范围值设置的值将用于所有连接(除非被连接属性覆盖)


    我在使用hibernate的应用程序中遇到了同样的错误。显然,RDS只在SSL握手期间进行客户端身份验证。您可以通过连接属性覆盖用于jdbc连接的密钥存储,而不是因为需要为应用程序使用单独的密钥存储而禁用客户端身份验证

  • 按照“更新JDBC的应用程序信任存储”一节中提到的步骤获取将用于RDS连接的客户端密钥库
  • 在示例代码中添加以下代码:
  • 通过执行上述操作,您可以覆盖将用于建立到RDS的连接的密钥库,同时使用单独的系统范围密钥库。请注意,每次要连接到RDS实例时,都需要设置属性

    如中所述:

    请注意,当一起使用时,连接属性将覆盖由其他两个方法设置的值。此外,使用连接属性设置的任何值仅在该连接中使用,而使用系统范围值设置的值将用于所有连接(除非被连接属性覆盖)