使用AWS SDK v3操作DynamoDB遇UnrecognizedClientException错误排查
问题:AWS SDK v3连接DynamoDB出现UnrecognizedClientException错误
测试AWS SDK v3编写的DynamoDB操作代码时,抛出错误:
UnrecognizedClientException: The security token included in the request is invalid.
错误栈如下:
Unit test for DynamoDb ' verifies successful response UnrecognizedClientException: The security token included in the request is invalid. 25 | const command = new GetItemCommand(params); 26 | console.log(command) > 27 | const result = await this.client.send(command); | ^ ^ 28 | return { body: JSON.stringify(unmarshall(result.Item || {})) }; } 29 | } catch (err: unknown) { 30 | throw err;
相关代码:
import { BatchGetItemCommand, BatchWriteItemCommand, BatchWriteItemCommandOutput, DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand } from '@aws-sdk/client-dynamodb'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; export class DynamoDb { private readonly tableName: string; private readonly client: DynamoDBClient; constructor(tableName = '') { this.client = new DynamoDBClient({ region: 'ap-northeast-1', credentials: { accessKeyId: 'xxxx', secretAccessKey: 'xxxxx', }, }); this.tableName = tableName ? tableName : ''; } public async get(keyName: string, key: string | number) { try { const params = { TableName: this.tableName, Key: marshall({ [keyName]: key }), }; const command = new GetItemCommand(params); console.log(command) const result = await this.client.send(command); return { body: JSON.stringify(unmarshall(result.Item || {})) }; } catch (err: unknown) { throw err; } } public async put(item: object) { try { const params = { TableName: this.tableName, Item: marshall(item), }; const command = new PutItemCommand(params); return await this.client.send(command); } catch (err: unknown) { throw err; } } public async update(keyName: string, key: string | number, updateExpression: string, expressionAttributeValues: { [key: string]: any }) { try { const params = { TableName: this.tableName, Key: marshall({ [keyName]: key }), UpdateExpression: updateExpression, ExpressionAttributeValues: marshall(expressionAttributeValues), ReturnValues: 'ALL_NEW', // Return the updated attributes of the item }; const command = new UpdateItemCommand(params); const result = await this.client.send(command); return { body: JSON.stringify(unmarshall(result.Attributes || {})) }; } catch (err: unknown) { throw err; } } public async batchGet(keys: { [keyName: string]: string | number }[]) { try { const params = { RequestItems: { [this.tableName]: { Keys: keys.map((key) => marshall(key)), }, }, }; const command = new BatchGetItemCommand(params); const result = await this.client.send(command); const responses = result.Responses?.[this.tableName] || []; const items = responses.map((response) => unmarshall(response) as object); return { body: JSON.stringify(items) }; } catch (err: unknown) { throw err; } } public async batchPut(items: object[]) { try { const putRequests = items.map((item) => ({ PutRequest: { Item: marshall(item), }, })); const params = { RequestItems: { [this.tableName]: putRequests, }, }; const command = new BatchWriteItemCommand(params); const result: BatchWriteItemCommandOutput = await this.client.send(command); return { body: JSON.stringify(result) }; } catch (err: unknown) { throw err; } } }
已知代码中已显式配置accessKeyId和secretAccessKey,且该密钥在其他代码中可正常连接DynamoDB,询问问题原因。
可能的原因及解决方法
- 测试环境凭证优先级覆盖:AWS SDK v3会优先从环境变量、本地
~/.aws/credentials文件或IAM角色加载凭证,可能你的测试环境里存在无效凭证(比如环境变量AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY被错误设置),覆盖了代码里显式配置的密钥。可以在测试代码里禁用凭证链查找,或者清理测试环境的相关环境变量。 - 凭证配置验证:在
DynamoDb构造函数里打印this.client.config.credentials,确认实际传入的密钥和你预期的有效密钥一致,避免代码里的占位符没替换、或者字符串拼写错误。 - 临时凭证缺失参数:如果使用的是STS生成的临时凭证,必须在
credentials里补充sessionToken字段,只传accessKeyId和secretAccessKey会导致验证失败。 - 区域或权限不匹配:确认你的DynamoDB表确实在
ap-northeast-1区域,且该密钥对应的IAM用户拥有该区域DynamoDB的操作权限(比如dynamodb:GetItem)。 - 测试框架干扰:部分测试框架(如Jest)可能会模拟AWS客户端或重置环境变量,检查测试代码中是否存在对
DynamoDBClient的Mock逻辑,或者是否有环境变量的重置操作。
内容的提问来源于stack exchange,提问作者kyoshida
相关产品推荐
相关产品推荐

