Alibaba Cloud 列レベルの暗号化ドライバー (JDBC) を使用して、Java アプリケーションからデータベース内の暗号化されたデータにアクセスします。このドライバーは、有効なマスター暗号化キー (MEK) を使用して、暗号文をプレーンテキストに自動的かつ透過的に復号します。
前提条件
-
列レベルの暗号化が有効になっている必要があります。詳細については、「列レベルの暗号化」をご参照ください。
説明列レベルの暗号化を有効にすると、ターゲットデータベースに rds_encdb 拡張がデフォルトでインストールされます。rds_encdb 拡張のステータスを確認するには、次の SQL ステートメントを実行します:
SELECT EXISTS (SELECT * FROM pg_extension WHERE extname = 'rds_encdb'); -
暗号化されたデータベースの接続情報 (ホスト名、ポート、データベース名、ユーザー名、パスワード) が必要です。インスタンスの内部エンドポイントまたはパブリックエンドポイントを取得する方法については、「エンドポイントとポート番号の表示と変更」をご参照ください。
-
データベースユーザーは、列レベルの暗号化の [暗号文権限 (JDBC 復号)] を持っている必要があります。詳細については、「列レベルの暗号化」をご参照ください。
注意事項
-
MEKを安全に保管してください。 -
JDK 1.8 以降のバージョンを使用してください。
操作手順
このトピックでは、Maven ベースの Java プロジェクトを例として使用します。
ステップ 1: Maven 依存関係の設定
Maven プロジェクトの pom.xml ファイルに次の依存関係を追加します。
<dependencies>
...
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>
...
</dependencies>
ステップ 2: URL と MEK の設定
JDBC で暗号化されたデータにアクセスする前に、MEK や URL などのパラメータを設定します。
|
パラメーター |
例 |
説明 |
|
MEK |
00112233445566778899aabbccddeeff |
ユーザー定義のマスター暗号化キーです。
警告
セキュリティ上の理由から、データベースは MEK の保存、管理、生成、バックアップを行いません。キーの生成とバックアップはお客様の責任となります。MEK を紛失すると、暗号化されたデータへのアクセスが永久に失われます。 |
|
URL |
jdbc:postgresql:encdb://%s:%s/%s |
列レベルの暗号化ドライバーを使用するには、URL プレフィックスを |
MEK の設定
MEK は 3 つの方法で設定できます。JDBC 接続で複数の方法を設定した場合、優先順位は次のとおりです:JDBC プロパティの設定 > ファイルの設定 > URL の設定。
-
URL の設定方法では、アンパサンド (
&) 文字を使用して複数のパラメーターを連結できます。 -
3 つの接続方法すべてにおいて、
MEKはクライアント側でローカルに処理され、エンベロープ暗号化を使用してサーバーに安全に配信されるため、外部に露出しません。
JDBC プロパティ
標準的な JDBC では、接続を確立する際に Properties オブジェクトでカスタム属性を設定できます。例:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
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=****
設定ファイルは、次の 2 つの場所のいずれかに配置できます。
-
encjdbc.confファイルをプロジェクトのresourcesディレクトリに配置します。 -
ファイルをプロジェクトのルートディレクトリ (アプリケーションの実行時ディレクトリ) に配置します。
MEK がファイルで設定されている場合、追加のコードは必要ありません。例:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String dbUrl = String.format("jdbc:postgresql:encdb://%s:%s/%s", hostname, port, dbname);
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... クエリを開始 ...
URL
MEK や ENC_ALGO などのパラメーターを URL に埋め込むことができます。例:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
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 プロパティの設定を使用して MEK を設定する完全な例です。このコードを実行する前に、ターゲットデータベースで列レベルの暗号化が設定されていることを確認してください。
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 {
// 実際の環境に基づいて、次の接続情報 (ホスト名、ポート、データベース名、ユーザー名、パスワード) を更新してください。
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(); // 接続を閉じます。
}
}