为什么在 Java 中本地使用 DynamoDB 时得到 "Unable to load AWS credentials"?

Why do I get "Unable to load AWS credentials" when using DynamoDB locally in Java?

我正在编写功能测试用例并连接到其中的本地 DyanmoDB 实例。

这是我创建 DynamoDB 客户端的方式:

private static final String table_name = "table-A";
private static String aws_region = "us-west-2";
private static AmazonDynamoDB amazonDynamoDBClient;
private static DynamoDB dynamoDB;


public static void initDB() {
    amazonDynamoDBClient = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
      new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", aws_region)).build();
    dynamoDB = new DynamoDB(amazonDynamoDBClient);
}

这就是我尝试创建 table:

的方式
Table table = dynamoDB.createTable(table_name,
                Arrays.asList(new KeySchemaElement("row_name", KeyType.HASH),
                        new KeySchemaElement("row_id", KeyType.RANGE)),
                Arrays.asList(new AttributeDefinition("row_name", ScalarAttributeType.S),
                        new AttributeDefinition("row_id", ScalarAttributeType.S)),
                new ProvisionedThroughput(10L, 10L));

但是,我得到以下异常:

com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain
        at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:131)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1115)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:764)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:728)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:721)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:704)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access0(AmazonHttpClient.java:672)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:654)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:518)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.doInvoke(AmazonDynamoDBClient.java:1831)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:1807)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.createTable(AmazonDynamoDBClient.java:636)
        at com.amazonaws.services.dynamodbv2.document.DynamoDB.createTable(DynamoDB.java:96)
        at com.amazonaws.services.dynamodbv2.document.DynamoDB.createTable(DynamoDB.java:108)
        at util.DBUtil.createAndInsertTestCases(DBUtil.java:24)
        at test.DocumentTest.createAndInsertDataInDB(DocumentTest.java:37)

问题是什么?

您似乎从未在您的计算机上为 AWS 设置任何凭证以供 SDK 使用。


如果您使用的是 DynamoDB 的本地或远程云版本,DynamoDB SDK 不会在意。这意味着它仍将在发送请求之前检查凭据是否存在。

由于大多数人将使用需要凭据的 DDB 远程云版本,这允许客户端在知道请求将失败时不调用远程服务器 - 更快的错误处理、无网络成本等。

您可以看到,堆栈跟踪显示 AmazonHttpClient.java 正在尝试使用 getCredentialsFromContext 获取凭据。


必须为所有请求设置访问密钥 ID 和秘密访问密钥,但对于本地 DDB,这些可以设置为任何虚拟值和假值。

这应该有效,例如:

EndpointConfiguration endpointConfig = new EndpointConfiguration("http://localhost:8000", aws_region);

AWSStaticCredentialsProvider awsCredProvider = new AWSStaticCredentialsProvider(new BasicAWSCredentials("fakeMyKeyId", "fakeSecretAccessKey"));

AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder
    .standard()
    .withCredentials(awsCredProvider)
    .withEndpointConfiguration(endpointConfig)
    .build();

正如@jarmod 在评论中指出的那样,如果您由于某种原因无法提供凭据,您也可以使用 AnonymousAWSCredentials(假设本地 DDB 实际上不需要签名 API 请求)。

将凭据提供程序指定为 AnonymousCredentialsProvider 可能有效:

EndpointConfiguration endpointConfig = new EndpointConfiguration("http://localhost:8000", aws_region);

AnonymousCredentialsProvider awsCredProvider = new AnonymousCredentialsProvider();

AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder
    .standard()
    .withCredentials(awsCredProvider)
    .withEndpointConfiguration(endpointConfig)
    .build();