gpt4 book ai didi

node.js - 为什么我的 AWS Lambda 函数返回 "Invalid JSON"错误?

转载 作者:行者123 更新时间:2023-12-04 11:36:44 26 4
gpt4 key购买 nike

我有一个我几天前写的 lambda 函数,它在测试时表现得非常好。今天去测试后(没有更改任何代码),我收到以下错误:"Invalid lambda function output : Invalid JSON" .

这是函数代码(Node.js 10.x):

const AWS = require("aws-sdk");
const joi = require("@hapi/joi");

const Cognito = new AWS.CognitoIdentityServiceProvider();

exports.handler = async (event) => {
// NOTE: Cognito expects Username to be the user's email

// Vars
const userPoolId = process.env.COGNITO_USER_POOL_ID;
const {email : UNSAFE_EMAIL, language : UNSAFE_LANGUAGE = "en-US"} = event;

// Normalize email and language
const UNSAFE_TRIMMED_EMAIL = UNSAFE_EMAIL.trim();
const UNSAFE_TRIMMED_LANGUAGE = UNSAFE_LANGUAGE.trim();

// Validate UNSAFE_INPUTS
const languageRegex = /^[a-z]{2}-[A-Z]{2}$/;

const schema = joi.object().keys({
email: joi.string().trim().email({minDomainSegments: 2}).required(),
language: joi.string().trim().min(2).max(5).regex(languageRegex).required()
});

const validationResult = joi.validate({
email: UNSAFE_TRIMMED_EMAIL,
language: UNSAFE_TRIMMED_LANGUAGE
}, schema);

if(validationResult.error) {
console.log(JSON.stringify(validationResult.error, null, 2));
return {
statusCode: 400,
body: JSON.stringify({
error: true,
error_message: "Invalid"
})
}
}

// Validation successful, change variable names to reflect
const VALIDATED_EMAIL = UNSAFE_TRIMMED_EMAIL;
const VALIDATED_LANGUAGE = UNSAFE_TRIMMED_LANGUAGE;

// Cognito params
// Username is the user's email
// email is also required in UserAttributes in order to send confirmation
// DesiredDeliveryMediums is required to send confirmation
const params = {
UserPoolId: userPoolId,
Username: VALIDATED_EMAIL,
UserAttributes: [
{
Name: "email",
Value: VALIDATED_EMAIL
},
{
Name: "custom:language",
Value: VALIDATED_LANGUAGE
}
],
DesiredDeliveryMediums: ["EMAIL"]
}

// Attempt to create user in Cognito
try {
const authRes = await Cognito.adminCreateUser(params).promise();
console.log("Success: ", JSON.stringify(authRes, null, 2));
return {
statusCode: 200,
body: JSON.stringify({
success: true
})
}
} catch(err) {
console.log("Error: ", JSON.stringify(err, null, 2));
return {
statusCode: 400,
body: JSON.stringify({
error: true,
error_message: err.message
})
}
}
};

运行测试时,我在传入格式错误的事件数据时收到预期的错误消息,并且在尝试使用相同的电子邮件创建用户两次时收到 Cognito 错误。再次,这是意料之中的。但是,当在用户池中没有用户的情况下传递有效电子邮件时,我得到以下响应(格式为可读性):
Response:
{
"statusCode": 400,
"body": {
"error": true,
"error_message": "Invalid lambda function output : Invalid JSON"
}
}

检查此函数连接到的 Cognito 用户池,我看到已成功创建用户。然而,没有像几天前那样向该电子邮件地址发送电子邮件。

记录的所有信息都是说我有一个无效的 JSON 错误,没有 authRes完全登录。删除对 Cognito 的调用和相应的 console.log 时调用,try 块成功运行。所以问题在于对 Cognito 的调用。

但是为什么这段代码在几天前运行良好时今天却失败了?这是让我非常沮丧的部分。

最佳答案

问题根本不在于这个 lambda 函数。这是 AWS 和我用作 Cognito 用户池的自定义消息触发器的 lambda 函数的问题。这是出了什么问题:

根据 AWS 文档,提供给自定义消息触发器 lambda 的事件数据采用以下形式用于 adminCreateUser函数调用:

{
"version": 1,
"triggerSource": "CustomMessage_AdminCreateUser",
"region": "<region>",
"userPoolId": "<userPoolId>",
"userName": "<userName>",
"callerContext": {
"awsSdk": "<calling aws sdk with version>",
"clientId": "<apps client id>",
...
},
"request": {
"userAttributes": {
"phone_number_verified": false,
"email_verified": true,
...
},
"codeParameter": "####",
"usernameParameter": "username"
},
"response": {
"smsMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailSubject": "<custom email subject>"
}
}

并且预计从自定义消息触发器 lambda 返回的数据与事件具有相同的形式 - 仅具有 response对象改变了。

所以这就是我为 lambda 写的:
const email_message = require("./email_message");

exports.handler = async (event) => {
// Vars
const {codeParameter, usernameParameter} = event.request;
console.log("Cognito Event: ", event);

// Check that codeParameter equals "####" and usernameParameter equals "username"
// This is to ensure that no compromised values are entered into the html
if(!(codeParameter === "####" && usernameParameter === "username")) {
return null;
}


const newRes = {
smsMessage: `Welcome: confirmation code is ${codeParameter} and username is ${usernameParameter}`,
emailMessage: email_message({codeParameter, usernameParameter}),
emailSubject: "Welcome To Our Site"
}

return {...event, response: newRes};
};

这在几天前测试时有效,因为事件对象是上面的形式。发生的事情是AWS偷偷改变了 codeParameter的内容。和 usernameParameter字段如下:
{
...
"codeParameter": "{####}",
"usernameParameter": "{username}",
...
}

所以 lambda 函数返回 null因为这些字符串没有通过验证 - 和 null不是有效的 JSON。

因此,临时解决方法是验证这些新字符串。然而,这引起了一些担忧。为什么 AWS 会突然更改事件对象而不更新文档?其次,我应该如何验证这些字符串是否可以安全地注入(inject)到客户的电子邮件地址中?我知道我可以 sanitizer usernameParameter但是 codeParameter怎么样?因为它很可能包含危险字符,例如 < > & ' "因为它是用随机符号生成的密码?如果自己生成密码,我可以确定它不会包含来自恶意行为者的数据,因此无需清理。但是,如果它来自 AWS,谁又能说这些值不会以某种方式受到损害呢?因此,为什么我首先添加了在这些值已更改的情况下应该失败的验证步骤。这正是发生的事情。

简而言之,我所有的代码都按预期运行。 AWS 在没有通知的情况下突然更改了他们的事件对象。

关于node.js - 为什么我的 AWS Lambda 函数返回 "Invalid JSON"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57583289/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com