列加密驱动(JDBC)

更新时间:2025-03-21 09:30:38
重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

若需通过Java应用程序访问数据库中的加密列数据,您可以使用阿里云提供的列加密驱动(JDBC)。在持有用户密钥的情况下,列加密驱动能够自动完成密文数据的解密并返回明文数据,该过程对应用程序是透明的。应用程序只需配置几行代码,即可接入列加密能力。

前提条件

  • 已开通列加密,详情请参见列加密

    说明

    开通列加密后,系统将默认在目标数据库中安装rds_encdb插件。您可以通过执行SQL语句来查询rds_encdb插件的状态:SELECT EXISTS (SELECT * FROM pg_extension WHERE extname = 'rds_encdb');

  • 已获取加密数据库连接信息。您首先需要获取加密数据库的连接信息,如域名(host)、端口(port)、数据库实例名(dbname)、用户名(username)、密码(password)等。实例内网或外网地址获取方式请参见查看或修改连接地址和端口

  • 已为数据库用户配置了列加密的密文权限(JDBC解密),详情请参见修改数据库账号权限

注意事项

  • 请保存好您设置的主密钥MEK

  • Java使用JDK 1.8或以上版本。

操作步骤

说明

本文以Maven构建Java项目为例。

步骤一:配置Maven依赖

Maven项目的pom.xml配置文件中加入以下依赖项。

<dependencies>
   ...
  <dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-cls-jdbc</artifactId>
    <version>1.0.10-1</version>
  </dependency>
   ...
</dependencies>

步骤二:配置URLMEK

通过JDBC访问数据库加密列的数据前,需要配置相关参数,包括MEK(主密钥)、URL(数据库连接信息)。

参数

取值示例(字符串类型)

说明

参数

取值示例(字符串类型)

说明

MEK

00112233445566778899aabbccddeeff

用户主密钥,由用户自定义。

  • 常见的生成方法有:密码生成工具(如openssl, openssl rand -hex 16)、编程语言中的random函数、或者从第三方密钥管理服务(KMS)获取。

  • 取值范围:长度为16字节的16进制字符串,且长度为32个字符。

警告

用户主密钥是您访问加密数据的根凭据,出于安全考虑,数据库不持有并管理您的主密钥,也不提供用户主密钥的生成和备份服务,您需要自行生成用户主密钥。一旦您丢失密钥,将无法再访问已有的数据。因此我们建议您妥善备份用户主密钥。

URL

jdbc:postgresql:encdb://%s:%s/%s

使用列加密驱动时,请将URL修改为以jdbc:postgresql:encdb://开头。

配置MEK

以下将介绍三种配置MEK的方法。如果您的JDBC同时配置了两种以上的方式,优先级顺序为:JDBC properties配置 > 文件配置 > URL配置。

说明
  • URL配置方式中,多个参数可以用&进行拼接。

  • 以下三种连接方式,MEK均在客户端本地进行处理、并以安全方式分发(信封加密)到服务端,始终保证MEK不泄露。

JDBC properties配置
文件配置
URL配置

标准的JDBC在建立连接时,可以通过Properties配置用户自定义属性。例如:

// 准备好域名(hostname)、端口(port)、数据库实例名(dbname)、用户名(username)、密码(password)等连接信息
// ...

String mek=****;

Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);


String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, props);

// ... 发起查询 ...

支持通过配置文件导入所需的参数,例如MEK。在项目中设置一个名为encJdbcConfigFile的属性,将其值指定为配置文件的路径。若未设置,该属性将默认使用 encjdbc.conf 文件。

配置文件的内容如下:

MEK=****

您可以通过以下两种方式放置配置文件的位置:

  • 将文件放入项目中的resources目录下,如下图所示:image.png

  • 将文件放入项目根目录,即程序的运行时目录。

通过文件配置MEK后,程序中无需额外配置,例如:

// 准备好域名(hostname)、端口(port)、数据库实例名(dbname)、用户名(username)、密码(password)等连接信息
// ...

String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... 发起查询 ...

支持通过URL链接中嵌入MEKENC_ALGO等参数。如下面所示:

// 准备好域名(hostname)、端口(port)、数据库实例名(dbname)、用户名(username)、密码(password)等连接信息
// ...

String mek=****;

String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... 发起查询 ...

完整示例代码

如下示例代码以JDBC properties配置MEK的方式为例。在进行JDBC访问之前,已完成目标数据库的列加密设置。

package org.example;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class Main {
    public static void main(String[] args) throws SQLException {
        // 以下连接信息(hostname、port、dbname、username、password)需要根据实际情况更新
        String hostname = "pgm-****.pg.rds.aliyuncs.com"; // 实例连接地址,请更新为实际值
        String port = "5432"; // 数据库端口,请更新为实际值
        String dbname = "testdb"; // 数据库名称,请更新为实际值
        String username = "user"; // 数据库用户名,请更新为实际具有密文权限(JDBC解密)的用户
        String password = "password"; // 数据库用户名的密码
        
        // 示例密钥,建议使用复杂度更高的密钥以确保安全
        String MEK = "00112233445566778899aabbccddeeff";
        
       // 创建数据库连接属性
        Properties props = new Properties();
        props.setProperty("user", username);
        props.setProperty("password", password);
        props.setProperty("MEK", MEK);

        // 格式化数据库连接URL
        String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);

        // 使用DriverManager获取数据库连接
        Connection connection = DriverManager.getConnection(dbUrl, props);

        // 执行查询以获取测试表中的数据
        ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM test_table");
        while (rs.next()) {
            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { // 列索引从1开始
                System.out.print(rs.getString(i) + "\t");
            }
            System.out.println(); // 换行
        }

        // 关闭资源
        rs.close();  // 关闭结果集
        connection.close(); // 关闭连接
    }
}
  • 本页导读
  • 前提条件
  • 注意事项
  • 操作步骤
  • 步骤一:配置Maven依赖
  • 步骤二:配置URL和MEK
  • 完整示例代码