本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用 Amazon Cognito 活动自定义工作流程
如果您是 Amazon Cognito Sync 的新用户,请使用 AWS AppSync
它允许同步用户数据,如应用程序首选项或游戏状态。它还通过允许多个用户实时同步和协作处理共享的数据,来扩展这些功能。
Amazon Cognito Events 允许您执行 AWS Lambda 函数以响应 Amazon Cognito 中的重要事件。当数据集得到同步时,Amazon Cognito 会引发同步触发事件。当用户更新数据时,您可以使用同步触发事件采取行动。该函数可以评估并有选择性地操作数据,然后,数据才会存储到云中并同步到用户的其他设备。这有利于在来自设备的数据同步到用户的其他设备之前对其进行验证,或者基于传入数据更新数据集中的其他值,如在玩家达到新级别时颁发奖励。
以下步骤将引导您设置每次 Amazon Cognito 数据集同步时都会执行的 Lambda 函数。
注意
使用 Amazon Cognito Events 时,您只能使用从 Amazon Cognito 身份获取的凭证。如果您关联了 Lambda 函数,但UpdateRecords
使用 AWS 账户证书(开发者证书)调用,则不会调用您的 Lambda 函数。
在中创建函数 AWS Lambda
要将 Lambda 与 Amazon Cognito 集成,您首先需要在 Lambda 中创建函数。为此,请执行以下操作:
在 Amazon Cognito 中选择 Lambda 函数
打开 Lambda 控制台。
单击“Create a Lambda function”(创建 Lambda 函数)。
在选择蓝图屏幕上,搜索并选择 “cognito-sync-trigger。”
在“Configure event sources”(配置事件源)屏幕上,将“Event source type”(事件源类型)设置保留为“Cognito Sync Trigger”,并选择您的身份池。单击“Next”(下一步)。
注意
在控制台外配置 Amazon Cognito Sync 触发器时,您必须添加 Lambda 基于资源的权限才能允许 Amazon Cognito 调用该函数。您可以从 Lambda 控制台(参见使用基于资源的策略 AWS Lambda)或使用 Lambda 操作添加此权限。AddPermission
Lambda 基于资源的策略示例
以下 AWS Lambda 基于资源的策略授予 Amazon Cognito 有限调用 Lambda 函数的能力。Amazon Cognito 只能在代表
aws:SourceArn
条件中的身份池和aws:SourceAccount
条件中的账户时才能调用该函数。{ "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "lambda-allow-cognito-my-function", "Effect": "Allow", "Principal": { "Service": "cognito-sync.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "
<your Lambda function ARN>
", "Condition": { "StringEquals": { "AWS:SourceAccount": "<your account number>
" }, "ArnLike": { "AWS:SourceArn": "<your identity pool ARN>
" } } } ] }在“Configure function”(配置函数)屏幕上,输入函数的名称和描述。将“Runtime”(运行时)设置保留为“Node.js”。在我们的示例中保留原来的代码。默认示例没有更改正在同步的数据。它只记录发生了 Amazon Cognito 同步触发事件这一事实。将“Handler name”(处理程序名称)设置保留为“index.handler”。在 “角色” 中,选择一个向您的代码授予访问权限的IAM角色 AWS Lambda。要修改角色,请访问IAM控制台。将“Advanced”(高级)设置保留不变。单击“Next”(下一步)。
在“Review”(查看)屏幕上,查看详细信息,并单击“Create function”(创建函数)。下一页面将显示您的新 Lambda 函数。
现在,Lambda 中已经写入了相应的函数,您需要选择该函数作为 Amazon Cognito Sync 触发事件的处理程序。以下步骤将指导您完成此过程。
从控制台主页:
单击要为其设置 Amazon Cognito Events 的身份池的名称。此时将显示身份池的“Dashboard”(控制面板)页。
在“Dashboard”(控制面板)页的右上角,单击“Manage Federated Identities”(管理联合身份)。出现“Manage Federated Identities”(管理联合身份)页。
向下滚动,并单击“Cognito Events”(Cognito 事件),以将其展开。
在 Sync Trigger (同步触发) 下拉菜单中,选择您希望在同步事件发生时触发的 Lambda 函数。
单击“Save Changes”(保存更改)。
现在,您的 Lambda 函数将在每次数据集同步时执行。下一部分将介绍如何在数据同步时读取和修改函数中的数据。
为同步触发编写 Lambda 函数
同步触发器遵循服务提供商接口使用的编程模式。Amazon Cognito 采用以下格式向您的 Lambda 函数提供输入。JSON
{ "version": 2, "eventType": "SyncTrigger", "region": "us-east-1", "identityPoolId": "identityPoolId", "identityId": "identityId", "datasetName": "datasetName", "datasetRecords": { "SampleKey1": { "oldValue": "oldValue1", "newValue": "newValue1", "op": "replace" }, "SampleKey2": { "oldValue": "oldValue2", "newValue": "newValue2", "op": "replace" },.. } }
Amazon Cognito 预计函数的返回值与输入格式相同。
编写同步触发器事件的函数时,应注意以下事项:
-
当 Amazon Cognito 在此期间调用您的 Lambda 函数时 UpdateRecords,该函数必须在 5 秒钟内做出响应。如果没有,则 Amazon Cognito Sync 服务将生成
LambdaSocketTimeoutException
异常。您无法增加此超时值。 -
如果您遇到了
LambdaThrottledException
异常,请再次尝试同步操作以更新记录。 Amazon Cognito 提供数据集中出现的所有记录,以作为函数的输入。
应用程序用户更新中将
op
字段设置为replace
的记录。删除的记录将op
字段设置为remove
。您可以修改任何记录,即使应用程序用户没有更新该记录也是如此。
除外,所有字段 datasetRecords 均为只读字段。请勿更改它们。如果您更改这些字段,则无法更新记录。
要修改记录的值,只需更新该值并将
op
设置为replace
。要删除记录,请将
op
设置为remove
,或将该值设置为空。要添加记录,请向 datasetRecords 数组中添加一条新记录。
Amazon Cognito 更新记录时,Amazon Cognito 会忽略响应中任何省略的记录。
示例 Lambda 函数
以下示例 Lambda 函数显示如何访问、修改和删除数据。
console.log('Loading function'); exports.handler = function(event, context) { console.log(JSON.stringify(event, null, 2)); //Check for the event type if (event.eventType === 'SyncTrigger') { //Modify value for a key if('SampleKey1' in event.datasetRecords){ event.datasetRecords.SampleKey1.newValue = 'ModifyValue1'; event.datasetRecords.SampleKey1.op = 'replace'; } //Remove a key if('SampleKey2' in event.datasetRecords){ event.datasetRecords.SampleKey2.op = 'remove'; } //Add a key if(!('SampleKey3' in event.datasetRecords)){ event.datasetRecords.SampleKey3={'newValue':'ModifyValue3', 'op' : 'replace'}; } } context.done(null, event); };