ReactJS从AWS Secrets Manager取凭证连接DynamoDB报错排查
问题排查:ReactJS从AWS Secrets Manager获取凭证后连接DynamoDB报错
报错信息
Uncaught (in promise) CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
硬编码AWS密钥时能正常连接DynamoDB,但通过Secrets Manager获取凭证后就触发上述错误。
原始代码
import * as AWS from 'aws-sdk'; const region = 'my-region'; const SecretId = "secret-name"; const client = new AWS.SecretsManager({ region: region }); client.getSecretValue({ SecretId: SecretId }).promise() .then((secretValue: any)=>{ const secretString = JSON.parse(secretValue.SecretString) console.log(secretString) AWS.config.update({ region: region, accessKeyId: secretString.AWS_ACCESS_KEY_ID, secretAccessKey: secretString.AWS_SECRET_ACCESS_KEY }); });
修改后的代码(仍报错)
import * as AWS from 'aws-sdk' const dynamoConnect = async () => { const secretName = "my-keys"; let secretsManager = new AWS.SecretsManager({ region: 'region' }); try { let secretValue = await secretsManager.getSecretValue({SecretId: secretName}).promise(); const creds = JSON.parse(secretValue.SecretString); AWS.config.update({ region: 'region', accessKeyId: creds.AWS_ACCESS_KEY_ID, secretAccessKey: creds.AWS_SECRET_ACCESS_KEY }); } catch (err) { throw err; } } const fetchData = async (tableName : any, studentId : any) => { const docClient = new AWS.DynamoDB.DocumentClient() await dynamoConnect() let params = { TableName: tableName, FilterExpression: `studentId = :studentId`, ExpressionAttributeValues: { ':studentId': studentId } } return data = await docClient.scan(params).promise(); }
错误原因
时序逻辑错误:fetchData中先初始化了docClient,之后才调用await dynamoConnect()更新全局AWS配置。此时docClient已经基于未更新的配置(无有效凭证)完成初始化,后续请求自然会报凭证缺失错误。
解决方案
方案1:先更新配置,再初始化客户端
调整fetchData的执行顺序,确保先完成凭证获取和配置更新,再创建docClient:
const fetchData = async (tableName : any, studentId : any) => { // 先完成凭证获取与配置更新 await dynamoConnect() // 基于更新后的全局配置初始化客户端 const docClient = new AWS.DynamoDB.DocumentClient() let params = { TableName: tableName, FilterExpression: `studentId = :studentId`, ExpressionAttributeValues: { ':studentId': studentId } } const data = await docClient.scan(params).promise(); return data; }
方案2:直接给客户端传入凭证(不依赖全局配置)
避免修改全局配置,直接将获取到的凭证传入DocumentClient的构造参数,逻辑更清晰:
import * as AWS from 'aws-sdk' const getAwsCredentials = async () => { const secretName = "my-keys"; const secretsManager = new AWS.SecretsManager({ region: 'region' }); const secretValue = await secretsManager.getSecretValue({SecretId: secretName}).promise(); return JSON.parse(secretValue.SecretString); } const fetchData = async (tableName : any, studentId : any) => { const creds = await getAwsCredentials(); // 直接传入凭证初始化客户端 const docClient = new AWS.DynamoDB.DocumentClient({ region: 'region', accessKeyId: creds.AWS_ACCESS_KEY_ID, secretAccessKey: creds.AWS_SECRET_ACCESS_KEY }); const params = { TableName: tableName, FilterExpression: `studentId = :studentId`, ExpressionAttributeValues: { ':studentId': studentId } } const data = await docClient.scan(params).promise(); return data; }
重要提醒
禁止在React前端项目中直接使用AWS SDK访问Secrets Manager和DynamoDB:前端代码会被用户浏览器解析,AWS密钥会直接暴露,导致严重的安全风险。正确的做法是通过后端API代理所有AWS服务请求,前端仅与后端交互。
内容的提问来源于stack exchange,提问作者Ranjan Kumar
相关产品推荐
相关产品推荐

