

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Java 示例
<a name="ddb-java-examples"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

以下示例为您演示如何使用适用于 DynamoDB 的 Java 客户端加密库来保护应用程序中的表项目。你可以在上的 aws-database-encryption-sdk-dynamodb 存储库的 [Java 示例中找到更多示例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)（并贡献自己的示例）。 GitHub

以下示例演示了如何在未填充的全新 Amazon DynamoDB 表中配置适用于 DynamoDB 的 Java 客户端加密库。如果您想配置现有的 Amazon DynamoDB 表以进行客户端加密，请参阅 [将版本 3.x 添加到现有表](ddb-java-config-existing-table.md)。

**Topics**
+ [使用 DynamoDB 增强版客户端](#ddb-java-enhanced-client-example)
+ [使用低级 DynamoDB API](#ddb-java-lowlevel-API-example)
+ [使用较低的级别 DynamoDbItemEncryptor](#ddb-java-itemencryptor)

## 使用 DynamoDB 增强版客户端
<a name="ddb-java-enhanced-client-example"></a>

以下示例展示了如何作为 DynamoDB API 调用的一部分，结合使用 DynamoDB 增强型客户端和 `DynamoDbEncryptionInterceptor` 与 [AWS KMS 密钥环](use-kms-keyring.md)对 DynamoDB 表项目进行加密。

您可以在 DynamoDB 增强版客户端中使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中 AWS KMS 一个密钥环。

**注意**  
DynamoDB 增强版客户端不支持[可搜索的加密](searchable-encryption.md)。将 `DynamoDbEncryptionInterceptor` 与低级 DynamoDB API 一起使用，以便使用可搜索加密。

**查看完整的代码示例**：[EnhancedPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/EnhancedPutGetExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：根据带注释的数据类创建表架构**  
以下示例使用带注释的数据类创建 `TableSchema`。  
此示例假设带注释的数据类和属性操作是使用 [SimpleClass.java 定义的。](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)有关为属性操作添加注释的更多指导，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。  
 AWS 数据库加密 SDK 不支持对[嵌套属性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)进行标注。

```
final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：创建加密配置**  
以下示例定义了一个 `tableConfigs` 映射，该映射表示 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
要使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)，您还必须在加密配置中包括 [`SearchConfig`](ddb-java-using.md#ddb-search-config)。

```
final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
tableConfigs.put(ddbTableName,
    DynamoDbEnhancedTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .schemaOnEncrypt(tableSchema)
        .build());
```

**步骤 5：创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 4** 中的 `tableConfigs` 中创建一个新的 `DynamoDbEncryptionInterceptor`。  

```
final DynamoDbEncryptionInterceptor interceptor =
    DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
        CreateDynamoDbEncryptionInterceptorInput.builder()
            .tableEncryptionConfigs(tableConfigs)
            .build()
    );
```

**第 6 步：创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 5 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`interceptor`。**  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步骤 7：创建 DynamoDB 增强版客户端并创建表**  
以下示例使用**步骤 6** 中创建的 AWS SDK DynamoDB 客户端创建 DynamoDB 增强型客户端，并使用带注释的数据类创建表。  

```
final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
        .dynamoDbClient(ddb)
        .build();
final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
```

**步骤 8：对表项目进行加密和签名**  
以下示例使用 DynamoDB 增强版客户端将项目放入 DynamoDB 表中。该项目在发送到 DynamoDB 之前将在客户端进行加密和签名。  

```
final SimpleClass item = new SimpleClass();
item.setPartitionKey("EnhancedPutGetExample");
item.setSortKey(0);
item.setAttribute1("encrypt and sign me!");
item.setAttribute2("sign me!");
item.setAttribute3("ignore me!");

table.putItem(item);
```

## 使用低级 DynamoDB API
<a name="ddb-java-lowlevel-API-example"></a>

以下示例演示如何使用带有 [AWS KMS 密钥环](use-kms-keyring.md)的低级 DynamoDB API，通过您的 DynamoDB `PutItem` 请求在客户端对项目自动进行加密和签名。

您可以使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中一个 AWS KMS 密钥环。

**查看完整的代码示例**：[BasicPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/BasicPutGetExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个 `attributeActionsOnEncrypt` 映射，该映射表示表项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：定义 DynamoDB 表的加密配置**  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
要使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)，您还必须在加密配置中包括 [`SearchConfig`](ddb-java-using.md#ddb-search-config)。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
tableConfigs.put(ddbTableName, config);
```

**步骤 5：创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 4** 中的 `tableConfigs` 创建 `DynamoDbEncryptionInterceptor`。  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)
                .build())
        .build();
```

**第 6 步：创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 5 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`interceptor`。**  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步骤 7：对 DynamoDB 表项目进行加密和签名**  
以下示例定义了一个 `item` 映射，该映射表示示例表项目并将该项目放入 DynamoDB 表中。该项目在发送到 DynamoDB 之前将在客户端进行加密和签名。  

```
final HashMap<String, AttributeValue> item = new HashMap<>();
item.put("partition_key", AttributeValue.builder().s("BasicPutGetExample").build());
item.put("sort_key", AttributeValue.builder().n("0").build());
item.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
item.put("attribute2", AttributeValue.builder().s("sign me!").build());
item.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final PutItemRequest putRequest = PutItemRequest.builder()
        .tableName(ddbTableName)
        .item(item)
        .build();

final PutItemResponse putResponse = ddb.putItem(putRequest);
```

## 使用较低的级别 DynamoDbItemEncryptor
<a name="ddb-java-itemencryptor"></a>

以下示例说明如何使用带有 [AWS KMS 密钥环](use-kms-keyring.md)的较低级别 `DynamoDbItemEncryptor` 来直接对表项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。

您可以在 DynamoDB 增强版客户端中使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中 AWS KMS 一个密钥环。

**注意**  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。将 `DynamoDbEncryptionInterceptor` 与低级 DynamoDB API 一起使用，以便使用可搜索加密。

**查看完整的代码示例**：[ItemEncryptDecryptExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/itemencryptor/ItemEncryptDecryptExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个 `attributeActionsOnEncrypt` 映射，该映射表示表项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：定义 `DynamoDbItemEncryptor` 配置**  
以下示例定义 `DynamoDbItemEncryptor` 的配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  

```
final DynamoDbItemEncryptorConfig config = DynamoDbItemEncryptorConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
```

**步骤 5：创建 `DynamoDbItemEncryptor`**  
以下示例使用**步骤 4** 中的 `config` 创建新的 `DynamoDbItemEncryptor`。  

```
final DynamoDbItemEncryptor itemEncryptor = DynamoDbItemEncryptor.builder()
        .DynamoDbItemEncryptorConfig(config)
        .build();
```

**步骤 6：直接对表项目进行加密和签名**  
以下示例使用 `DynamoDbItemEncryptor` 直接对项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。  

```
final Map<String, AttributeValue> originalItem = new HashMap<>();
originalItem.put("partition_key", AttributeValue.builder().s("ItemEncryptDecryptExample").build());
originalItem.put("sort_key", AttributeValue.builder().n("0").build());
originalItem.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
originalItem.put("attribute2", AttributeValue.builder().s("sign me!").build());
originalItem.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final Map<String, AttributeValue> encryptedItem = itemEncryptor.EncryptItem(
        EncryptItemInput.builder()
                .plaintextItem(originalItem)
                .build()
).encryptedItem();
```