凭据JDBC客户端

针对使用JDBC方式连接数据库的业务场景,您将数据库账号密码保存在RDS凭据或通用凭据后,应用可以集成凭据JDBC客户端,通过在KMS托管的凭据完成数据库连接身份鉴别。本文介绍如何安装和使用凭据JDBC客户端。

SDK介绍

凭据JDBC客户端是针对使用JDBC方式连接数据库的业务场景,该客户端自动从KMS获取凭据用于数据库连接身份鉴别,更便于您集成。其他获取和使用凭据的业务场景推荐您优先使用凭据客户端,其次是KMS实例SDK和阿里云SDK。详细信息,请参见SDK参考

说明

如果您需要对凭据进行管控类操作,仅支持使用阿里云SDK。

凭据JDBC客户端具有以下功能特性:

  • 支持Java数据库连接(Java Database Connectivity,简称JDBC),包括在数据库连接池(例如c3p0和DBCP)和数据源中通过JDBC连接数据库。

  • 支持MySQL、SQL Server、PostgreSQL和MariaDB四种数据库类型。

  • 支持用户自定义凭据刷新频率。

注意事项

  • 支持的凭据类型:通用凭据、RDS凭据。

    • 如果是RDS凭据,建议您使用双账号托管的RDS凭据。

    • 如果是通用凭据,凭据值为JSON格式且内容格式如下。

      {
          "AccountName":"<您的数据库账号用户名>",
          "AccountPassword":"<您的数据库账号密码>"
      }
  • 支持的开发语言:Java(Java 8及以上版本)。

  • 支持的访问凭证:AccessKey、RAM角色、ECS RAM角色、STS、ClientKey

步骤一:创建访问凭证

重要
  • AccessKey、RAM角色、ECS RAM角色、STS仅支持通过KMS服务Endpoint获取凭据值,ClientKey既支持通过KMS服务Endpoint,也支持通过KMS实例Endpoint获取凭据值。关于Endpoint的详细介绍,请参见Endpoint说明

  • KMS实例Endpoint支持更高的性能,因此推荐您使用ClientKey通过KMS实例Endpoint获取凭据值。

AccessKey

具体操作,请参见创建AccessKey

RAM角色

  1. 创建RAM角色。具体操作,请参见创建RAM角色

  2. 获取目标RAM角色的RamRoleArn。具体操作,请参见查看RAM角色

    说明

    RamRoleArn是RAM角色的ARN信息,即需要扮演的角色ID。格式为acs:ram::$accountID:role/$roleName。$accountID为阿里云账号ID。$roleName为RAM角色名称。

ECS RAM角色

为ECS实例授予RAM角色。具体操作,请参见通过ECS实例RAM角色授权ECS访问其他云服务

STS

  1. 创建RAM用户或RAM角色。具体操作,请参见创建RAM用户创建RAM角色

  2. 为RAM用户或RAM角色授予AliyunSTSAssumeRoleAccess权限。具体操作,请参见为RAM用户授权为RAM角色授权

  3. 使用RAM用户或RAM角色调用STS服务的AssumeRole接口获取STS临时访问凭证。具体操作,请参见AssumeRole - 获取扮演角色的临时身份凭证

ClientKey

您需要先创建应用接入点AAP,然后在AAP中创建ClientKey。具体操作,请参见创建应用接入点

步骤二:安装客户端

访问aliyun-secretsmanager-jdbc了解更多安装信息和源代码。

通过Maven的方式安装凭据JDBC客户端。

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-secretsmanager-jdbc</artifactId>
    <version>x.x.x</version>
</dependency>
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-core</artifactId>
  <version>4.x.x</version>
</dependency>
说明

建议您安装最新版本的SDK。

步骤三:通过配置文件(secretsmanager.properties)设置客户端运行参数

在项目的运行代码中新增配置文件secretsmanager.properties,不同访问凭证需要配置的参数不同。

AccessKey

## 访问凭据类型
credentials_type=ak
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## 关联的KMS服务地域
cache_client_region_id=[{"regionId":"#regionId#"}]
## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
refresh_secret_ttl=21600000

RAM角色

## 访问凭据类型
credentials_type=ram_role
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## 访问凭据Session名称
credentials_role_session_name=#credentials_role_session_name#
## RAM Role ARN
credentials_role_arn=#credentials_role_arn#
## 访问凭据Policy
credentials_policy=#credentials_policy#
## 关联的KMS服务地域
cache_client_region_id=[{"regionId":"#regionId#"}]
## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
refresh_secret_ttl=21600000

ECS实例RAM角色

## 访问凭据类型
credentials_type=ecs_ram_role
## ECS RAM Role名称
credentials_role_name=#credentials_role_name#
## 关联的KMS服务地域
cache_client_region_id=[{"regionId":"#regionId#"}]
## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
refresh_secret_ttl=21600000

STS

## 访问凭据类型
credentials_type=sts
## Access Key Id
credentials_access_key_id=#credentials_access_key_id#
## Access Key Secret
credentials_access_secret=#credentials_access_secret#
## 访问凭据Session名称
credentials_role_session_name=#credentials_role_session_name#
## RAM Role ARN
credentials_role_arn=#credentials_role_arn#
## 访问凭据Policy
credentials_policy=#credentials_policy#
## 关联的KMS服务地域
cache_client_region_id=[{"regionId":"#regionId#"}]
## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
refresh_secret_ttl=21600000

ClientKey

  • 访问KMS服务Endpoint

    ## 访问凭据类型
    credentials_type=client_key
    ## 读取client key的解密密码:支持从环境变量或者文件读取
    client_key_password_from_env_variable=#your client key private key password environment variable name#
    client_key_password_from_file_path=#your client key private key password file path#
    ## 关联的KMS服务地域
    cache_client_region_id=[{"regionId":"#regionId#"}]
    ## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
    ## 下面的配置将凭据刷新频率设定为1小时
    refresh_secret_ttl=3600000
    client_key_file_path=#your client key file path# 
  • 访问KMS实例Endpoint

    • 方式一:通过文件获取ClientKey凭证口令

      您还需要将password配置到文件中,文件名称由您自定义,但需要和passwordFromFilePath的取值相同。

      cache_client_dkms_config_info=[{"regionId":"<your dkms region>","endpoint":"<your dkms endpoint>","passwordFromFilePath":"< your password file path >","clientKeyFile":"<your Client Key file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]

      配置示例

      cache_client_dkms_config_info=[{"regionId":ch-hangzhou","endpoint":"kst-hzz634e67d126u9p9****.cryptoservice.kms.aliyuncs.com","passwordFromFilePath":"C:\RamSecretPlugin\src\main\resources\clientKeyPassword.txt","clientKeyFile":"C:\RamSecretPlugin\src\main\resources\clientKey_KAAP.json","ignoreSslCerts":false,"caFilePath":"C:\RamSecretPlugin\src\main\resources\PrivateKmsCA_kst-hzz634e67d126u9p9****.pem"}]
    • 方式二:通过环境变量获取ClientKey凭证口令

      您还需要将password配置到系统环境变量中,变量名称由您自定义,但需要和passwordFromEnvVariable的取值相同。

      cache_client_dkms_config_info=[{"regionId":"<your dkms region>","endpoint":"<your dkms endpoint>","passwordFromEnvVariable":"<your_password_env_variable>","clientKeyFile":"<your ClientKey file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]

    各配置项说明:

    配置项

    配置项含义

    说明

    regionId

    KMS实例所在地域ID。

    具体的地域ID,请参见地域和接入地址

    endpoint

    KMS实例的域名地址,格式为{实例ID}.kms.aliyuncs.com

    在控制台实例管理页面,单击目标KMS实例,在实例详情页面查看实例VPC地址,将https://去掉后即为KMS实例的域名地址。

    clientKeyFile

    ClientKey文件(JSON格式)的绝对路径或相对路径。

    • ClientKey文件:在应用接入点AAP中创建ClientKey时下载的应用身份凭证内容(ClientKeyContent),下载后文件名默认为ClientKey_******.json。

    • 凭证口令:在应用接入点AAP中创建ClientKey时下载的凭证口令(ClientKeyPassword),下载后文件名默认为ClientKey_******_password.txt。

    重要

    ClientKey文件和凭证口令是一一对应的,仅支持您在创建ClientKey时获取。如果您在创建时未保存,则需要在应用接入点AAP中重新创建ClientKey。更多详细内容,请参见创建应用接入点

    passwordFromFilePathpasswordFromEnvVariable

    • passwordFromFilePath:从文件中获取凭证口令,取值为文件的绝对路径或相对路径。您需要将凭证口令保存到文件中。

    • passwordFromEnvVariable:从环境变量获取凭证口令,取值为环境变量名称。您需要将凭证口令配置到环境变量中。

    ignoreSslCerts

    是否忽略KMS实例SSL证书的有效性检查。KMS实例内置SSL证书,使用SSL/TLS协议用于身份验证和加密通信。取值:

    • true:表示忽略,不检查KMS实例SSL证书的有效性。

      说明

      取值为true时,无需配置caFilePath

    • false:表示验证,检查KMS实例SSL证书的有效性。

    正式生产环境中,请将该值设置为false。

    caFilePath

    KMS实例CA证书文件的绝对路径或相对路径。

    KMS实例CA证书,用于检查KMS实例SSL证书的有效性。例如:检查KMS实例SSL证书是否由对应的CA中心签发、是否在有效期内、以及对应的域名是否为KMS实例的域名地址(endpoint)。

    实例管理页面,单击获取实例CA证书区域的下载,下载KMS实例的CA证书。

步骤四:使用凭据JDBC客户端连接数据库

重要

示例中仅介绍必须修改的属性,其他属性请您根据实际业务情况进行填写。

通过JDBC方式连接数据库

  • MySQL数据库

    说明

    请将#your-mysql-secret-name#<your-mysql-ip><your-mysql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class SecretManagerJDBCSample {
        public static void main(String[] args) throws Exception {
            // 加载阿里云凭据JDBC客户端 Load the JDBC Driver com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
            Class.forName("com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver");
            Connection connect = null;
            try {
                connect = DriverManager.getConnection("secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>", "#your-mysql-secret-name#","");
            } catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
  • SQLServer数据库

    说明

    请将#your-sqlserver-secret-name#<your-sqlserver-ip><your-sqlserver-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class SecretManagerJDBCSqlServerSample {
    
        public static void main(String[] args) throws Exception{
            // 加载阿里云凭据JDBC客户端 Load the JDBC Driver com.aliyun.kms.secretsmanager.MssqlSecretsManagerSimpleDriver
            Class.forName("com.aliyun.kms.secretsmanager.MssqlSecretsManagerSimpleDriver");
            Connection connect = null;
            try {
                connect = DriverManager.getConnection("secrets-manager:sqlserver://<your-sqlserver-ip>:<your-sqlserver-port>;databaseName=<your-database-name>", "#your-sqlserver-secret-name#", "");
            }  catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
  • PostgreSQL数据库

    说明

    请将#your-postgresql-secret-name#<your-postgresql-ip><your-postgresql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class SecretManagerJDBCPostgreSQLSample {
        public static void main(String[] args) throws Exception {
            // 加载阿里云凭据JDBC客户端 Load the JDBC Driver com.aliyun.kms.secretsmanager.PostgreSQLSecretManagerSimpleDriver
            Class.forName("com.aliyun.kms.secretsmanager.PostgreSQLSecretManagerSimpleDriver");
            Connection connect = null;
            try {
                connect = DriverManager.getConnection("secrets-manager:postgresql://<your-postgresql-ip>:<your-postgresql-port>/<your-database-name>", "#your-postgresql-secret-name#", "");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
  • MariaDB数据库

    说明

    请将#your-mariadb-secret-name#<your-mariadb-ip><your-mariadb-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class SecretManagerJDBCMarialDBSample {
    
    	public static void main(String[] args) throws Exception{
    		// 加载阿里云凭据JDBC客户端 Load the JDBC Driver com.aliyun.kms.secretsmanager.MariaDBSecretManagerSimpleDriver
    		Class.forName("com.aliyun.kms.secretsmanager.MariaDBSecretManagerSimpleDriver");
    		Connection connect = null;
    		try {
    			connect = DriverManager.getConnection("secrets-manager:mariadb://<your-mariadb-ip>:<your-mariadb-port>/<your-database-name>", "#your-mariadb-secret-name#", "");
    		}  catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    }

通过数据库连接池连接数据库

请按如下方式设置c3p0配置文件(c3p0.properties)中的c3p0.userc3p0.driverClassc3p0.jdbcUrlc3p0.user为凭据名称,c3p0.driverClass为阿里云凭据JDBC Driver类名称,c3p0.jdbcUrl需要以secrets-manager开头。

  • MySQL数据库

    说明

    请将#your-mysql-secret-name#<your-mysql-ip><your-mysql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    c3p0.user=#your-mysql-secret-name#
    c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
    c3p0.jdbcUrl=secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>
  • SQLServer数据库

    说明

    请将#your-sqlserver-secret-name#<your-sqlserver-ip><your-sqlserver-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    c3p0.user=#your-sqlserver-secret-name#
    c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
    c3p0.jdbcUrl=secrets-manager:sqlserver://<your-sqlserver-ip>:<your-sqlserver-port>/<your-database-name>
  • PostgreSQL数据库

    说明

    请将#your-postgresql-secret-name#<your-postgresql-ip><your-postgresql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    c3p0.user=#your-postgresql-secret-name#
    c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
    c3p0.jdbcUrl=secrets-manager:postgresql://<your-postgresql-ip>:<your-postgresql-port>/<your-database-name>
  • MariaDB数据库

    说明

    请将#your-mariadb-secret-name#<your-mariadb-ip><your-mariadb-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

    c3p0.user=#your-mariadb-secret-name#
    c3p0.driverClass=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
    c3p0.jdbcUrl=secrets-manager:mariadb://<your-mariadb-ip>:<your-mariadb-port>/<your-database-name>

通过数据源(DataSource)连接数据库

以使用c3p0 ComboPooledDataSource、MySQL数据库为例,在Spring配置文件中增加如下配置。

说明

请将#your-mysql-secret-name#<your-mysql-ip><your-mysql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
      <property name="driverClass" value="com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver" />
      <property name="user" value="#your-mysql-secret-name#" />
      <property name="jdbcUrl" value="secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>" />
      <property name="maxPoolSize" value="***" />
      <property name="minPoolSize" value="***" />
      <property name="initialPoolSize" value="***" />
  </bean>
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
      <property name="dataSource" ref="dataSource" />
  </bean>
说明

请您根据实际需求设置maxPoolSize、minPoolSize和initialPoolSize参数值。

通过Druid连接池连接数据库

以MySQL数据库为例,您需要修改配置文件中的如下属性。

说明

请将#your-mysql-secret-name#<your-mysql-ip><your-mysql-port><your-database-name>替换为您实际使用的凭据名称、服务器IP地址、端口、数据库名称。

  • properties配置文件方式

    username=#your-mysql-secret-name#
    driverClassName=com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
    url=secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>
  • bean配置方式

    • 方式一:XML配置文件

      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
           <property name="username" value="${your-mysql-secret-name}" />
           <property name="driverClassName" value="com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver" />
           <property name="url" value="secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>" />
      </bean>
      
    • 方式二:配置属性注入

      在应用中新建一个加载数据库连接信息的驱动类。

      @Configuration
      public class DataConfig {
      
          @Value("${your-mysql-secret-name}")
          private String username;
      
          @Value("com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver")
          private String driverClassName;
      
          @Value("secrets-manager:mysql://<your-mysql-ip>:<your-mysql-port>/<your-database-name>")
          private String url;
      
          @Bean(name = "dataSource",initMethod = "init",destroyMethod = "close")
          public DruidDataSource dataSource(){
              DruidDataSource druidDataSource = new DruidDataSource();
              druidDataSource.setUsername(username);
              druidDataSource.setDriverClassName(driverClassName);
              druidDataSource.setUrl(url);
              return druidDataSource;
          }
      }