使用.Net Core 1.0 Lambda我希望能够创建一个Lambda函数,该函数处理来自AWS Cognito用户池的PreSignUp触发器。
using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public class PreSignUp_SignUp
{
public string userPoolId { get; set; }
public const string EmailKey = "email";
public const string PhoneNumber = "phone_number";
public Dictionary<string,string> userAttributes { get; set; }
public Dictionary<string, string> validationData { get; set; }
}
public class PreSignup_SignUpResponse
{
public bool autoConfirmUser { get; set; }
}
public class Function
{
public PreSignup_SignUpResponse FunctionHandler(PreSignUp_SignUp input, ILambdaContext context)
{
return new PreSignup_SignUpResponse { autoConfirmUser = true };
}
}
虽然请求成功并在使用示例请求调用Lambda时返回响应:
{
"datasetName": "datasetName",
"eventType": "SyncTrigger",
"region": "us-east-1",
"identityId": "identityId",
"datasetRecords": {
"SampleKey2": {
"newValue": "newValue2",
"oldValue": "oldValue2",
"op": "replace"
},
"SampleKey1": {
"newValue": "newValue1",
"oldValue": "oldValue1",
"op": "replace"
}
},
"identityPoolId": "identityPoolId",
"version": 2
}
当通过.Net AmazonCognitoIdentityProviderClient执行实际的SignUp时,我收到错误:
Amazon.CognitoIdentityProvider.Model.InvalidLambdaResponseException: 无法识别的lambda输出
我的猜测意味着我没有得到响应的形状(甚至可能是请求)正确。
有没有人有一个.Net Lambda函数的例子适用于AWS Cognito中的PreSignUp触发器?
答案 0 :(得分:10)
Cognito触发器请求/响应必须包含Cognito触发器文档中指定的整个有效负载:
我发现在诊断这个问题时,最好的起点是创建一个函数处理程序,它接受一个JObject,然后记录并返回相同的对象,例如。
public JObject FunctionHandler(JObject input, ILambdaContext context)
{
context.Logger.LogLine("Input was: " + input);
return input;
}
这可以捕获cloudwatch日志中的有效负载,然后帮助引导您进入所需的强类型结构。
在我的PreSignUp案例中,我最终创建了以下类型,以创建一个简单的函数,自动验证所有提供的凭据。
public abstract class AbstractTriggerRequest
{
[JsonProperty("userAttributes")]
public Dictionary<string, string> UserAttributes { get; set; }
}
public abstract class AbstractTriggerResponse
{
}
public class TriggerCallerContext
{
[JsonProperty("awsSdkVersion")]
public string AwsSdkVersion { get; set; }
[JsonProperty("clientId")]
public string ClientId { get; set; }
}
public abstract class AbstractTriggerBase<TRequest, TResponse>
where TRequest: AbstractTriggerRequest
where TResponse: AbstractTriggerResponse
{
[JsonProperty("version")]
public int Version { get; set; }
[JsonProperty("triggerSource")]
public string TriggerSource { get; set; }
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("userPoolId")]
public string UserPoolId { get; set; }
[JsonProperty("callerContext")]
public TriggerCallerContext CallerContext { get; set; }
[JsonProperty("request")]
public TRequest Request { get; set; }
[JsonProperty("response")]
public TResponse Response { get; set; }
[JsonProperty("userName", NullValueHandling = NullValueHandling.Ignore)]
public string UserName { get; set; }
}
public class PreSignUpSignUpRequest : AbstractTriggerRequest
{
[JsonProperty("validationData")]
public Dictionary<string,string> ValidationData { get; set; }
}
然后Lambda函数以下面的签名结束:
public class Function
{
public PreSignUp_SignUp FunctionHandler(PreSignUp_SignUp input, ILambdaContext context)
{
context.Logger.LogLine("Auto-confirming everything!");
input.Response = new PreSignUpSignUpResponse {
AutoConfirmUser = true,
// you can only auto-verify email or phone if it's present in the user attributes
AutoVerifyEmail = input.Request.UserAttributes.ContainsKey("email"),
AutoVerifyPhone = input.Request.UserAttributes.ContainsKey("phone_number")
};
return input;
}
}
希望这有助于其他人遇到为Cognito编写Lambda触发器的问题。
答案 1 :(得分:2)
前两个响应现在不准确,除非您仍然使用旧的、性能较低的 Amazon.Lambda.Serialization.Json.JsonSerializer
。这个旧的序列化器使用 Newtonsoft.Json
,而新的 Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer
实现了最近的 System.Text.Json
。
因此,JObject
参数不再合适,应替换为 JsonElement
。如果您尝试将 JObject
与这个新的序列化程序一起使用,您将收到一个错误,因为序列化程序不知道如何处理这个对象。
您应该阅读 this 以更好地了解它的工作原理,但您可以使用 JsonElement
访问 GetProperty("[insert property name here]")
的属性。
例如:
public async Task<JsonElement> FunctionHandler(JsonElement input, ILambdaContext context)
{
var request = input.GetProperty("request");
var userAttributes = request.GetProperty("userAttributes");
string email = userAttributes.GetProperty("email").GetString();
return input;
}
这样,您无需构建整个类来容纳所需的请求和响应参数,只需获取和设置所需的属性即可。
答案 2 :(得分:1)
这里已经有了另一个很好的答案。但是,我不是专业的.NET开发人员,所以这个解决方案对我来说更有意义。
class AutoVerifyEmail
{
public AutoVerifyEmail() { }
public JObject AutoVerifyEmailPreSignup(JObject input, ILambdaContext context)
{
//Console.Write(input); //Print Input
input["response"]["autoVerifyEmail"] = true;
input["response"]["autoConfirmUser"] = true;
return input;
}
}