☰
使用 AWS SDK for JavaScript (v3) 与 Lambda 构建浏览器直调 DynamoDB 的 Web 应用
2026/9/25 6:12:55 网站建设 项目流程
  • 示例工程
  • 教程
  • 后端

【免费下载链接】aws-doc-sdk-examples

Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.

项目地址:https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples
点击查看免费下载

导读

本文以 AWS 官方代码示例仓库aws-doc-sdk-examples中的 lambda-for-browser 教程为主体,完整讲解如何用 AWS SDK for JavaScript (V3) 在浏览器中直接触发 Lambda 函数,将用户提交的数据写入 Amazon DynamoDB。你将掌握 Amazon Cognito 身份池、未认证访客角色、Lambda 函数打包部署与浏览器端 webpack 打包的完整链路,最终搭建一个可独立运行的前后端分离 Web 应用,并理解浏览器场景下 AWS 凭据分发与函数直调的安全边界。

场景与整体架构

本示例演示的是典型的“浏览器直调 AWS 服务”模式:前端页面不经过任何自建服务器,直接通过 AWS SDK 调用 Lambda 函数,由 Lambda 代表客户端完成 DynamoDB 写入。整个链路涉及四种 AWS 服务:

  • Amazon Cognito:提供身份池(Identity Pool),为未登录的“访客”(Guest)颁发临时 AWS 凭据,让浏览器可以安全调用 AWS API。
  • AWS Lambda:承载业务逻辑——接收浏览器发来的事件负载,并把数据写入 DynamoDB。
  • Amazon DynamoDB:最终的数据存储目标,保存前端提交的颜色(Color)与图案(Pattern)等字段。
  • AWS Identity and Access Management (IAM):通过身份池的访客角色(Guest Role)与 Lambda 执行角色控制两侧权限边界。

从源码结构看,整个示例分为两个独立工程,均位于 javascriptv3/example_code/cross-services/lambda-for-browser 目录下:

  • 前端工程frontend/:由 HTML 表单、src/index.js 与 src/lambdaClient.js 组成,通过 webpack 打包后以静态资源形式提供。
  • 后端工程lambda/:包含 src/index.js、ddbClient.js与ddbDocClient.js,被打包成 ESM 模块压缩包后上传为 Lambda 函数。

数据流为:浏览器表单 → Lambda 客户端(携带 Cognito 访客凭据)→InvokeCommand触发 Lambda → Lambda 内 DynamoDB Document Client 执行PutCommand→ 记录写入lambda-for-browser表。

环境准备与前置要求

开始前需要准备以下条件:

  • AWS 账户:用于创建 Cognito 身份池、DynamoDB 表与 Lambda 函数,具体账户与 SDK 配置方法可参考仓库根目录 README.md 及官方《AWS SDKs and Tools Reference Guide》。
  • Node.js 环境:用于安装依赖、执行 webpack 打包。仓库示例的package.json以@aws-sdk/*3.370.0 系列包为基础,建议使用 Node.js 18+(ESM 模块输出依赖现代运行时支持)。

注意事项与成本提示

  • 按最小权限原则(least privilege)配置角色,仅授予完成任务所需的最低权限;本示例涉及的全部服务均在 AWS Free Tier 免费套餐覆盖范围内,但教程完成后务必终止所有资源,避免产生持续费用。
  • 该示例未在全部 AWS 区域验证,部分服务仅在特定 Region 提供,请确认所用区域的服务可用性。
  • 控制台操作时请注意选择正确的 Region,并在创建各资源时保持 Region 一致——前端lambdaClient.js中的REGION必须与身份池、Lambda、DynamoDB 所在区域匹配。

第一步:创建 Cognito 身份池与访客角色

浏览器无法持有长期密钥,因此本示例采用Cognito 身份池 + 未认证访客访问的经典方案:身份池会为未登录用户签发临时 AWS 凭据。

创建步骤如下:

  1. 打开 Amazon Cognito 控制台,在侧边栏选择Identity pools(身份池)。
  2. 点击Create identity pool(创建身份池)。
  3. 勾选Guest access(访客访问)复选框——这是允许浏览器匿名调用 AWS API 的关键开关。
  4. 选择Next。
  5. 选择Create a new IAM role(创建新的 IAM 角色)。
  6. 在IAM role字段中输入角色名称,例如lambda-for-browser-guest-role。
  7. 点击Next,输入身份池名称(例如lambda-for-browser-identity-pool)。
  8. 再次点击Next,核对信息后点击Create identity pool(创建身份池)。

创建完成后,在身份池详情页找到Identity pool ID(形如<区域>:<随机字符串>),稍后需要把它填入前后端两处源码的IDENTITY_POOL_ID常量中。

访客角色的安全边界

默认生成的访客角色权限策略较宽泛,而本示例浏览器端唯一需要执行的动作是调用 Lambda,因此按最小权限原则应收紧为仅lambda:InvokeFunction。按 README.md 的指引,在 IAM 控制台找到访客角色,在Permissions选项卡展开默认策略并点击Edit,将策略 JSON 替换为:

{ "Version": "2012-10-17", "Statement": [ { "Action": "lambda:InvokeFunction", "Resource": "*", "Effect": "Allow" } ] }

保存后,浏览器端通过 Cognito 身份池拿到的临时凭据就只具备触发 Lambda 的权限,无法直接读写 DynamoDB、S3 等其他资源。这既是安全的底线,也体现了“浏览器只负责发起请求、敏感操作后移到 Lambda”的设计原则。

第二步:创建 DynamoDB 表

在 DynamoDB 控制台 中创建目标数据表:

  1. 点击Create table(创建表)。
  2. Table name(表名)填写lambda-for-browser。README 明确指出:表名必须与前端 frontend/src/index.js 中的TableName完全一致,否则写入会失败。
  3. Partition key(分区键)填写Id,类型选择Number。前端每次提交都会生成一个 1–10000 之间的随机整数作为Id(见下文源码分析)。
  4. Sort key(排序键)留空——本示例没有任何查询操作,排序键无关紧要。
  5. 其余选项保持Default settings(默认设置)不变,点击Create table完成创建。

第三步:打包 Lambda 后端

后端函数代码位于 lambda/src 目录。Lambda 运行时本身已包含 AWS SDK,因此后端打包并非必需;这里之所以仍用 webpack 打包,是为了让代码更小、结构更紧凑。需要注意:@aws-sdk/*相关依赖被显式排除在打包产物之外,这一配置定义在 lambda/webpack.config.js 中。

打包配置要点

lambda/webpack.config.js 的关键配置如下:

  • externalsType: "module"与experiments.outputModule: true:输出标准的 ES Module。
  • output.filename: "index.mjs":产物文件名为index.mjs。
  • output.library.type: "module":以 ESM 库形式导出。
  • externals数组列出@aws-sdk/client-cognito-identity、@aws-sdk/client-dynamodb、@aws-sdk/client-iam、@aws-sdk/credential-provider-cognito-identity、@aws-sdk/lib-dynamodb五个包——这些包在 Lambda 运行环境中由运行时提供,无需打进压缩包。

打包与上传步骤

按 README 的完整流程执行:

  1. 替换身份池 ID:打开 lambda/src/ddbClient.js,把IDENTITY_POOL_ID = "IDENTITY_POOL_ID"替换为第一步创建的身份池 ID。
  2. 进入lambda目录:cd lambda。
  3. 安装依赖:npm i。
  4. 执行打包:npm run build——该脚本对应 lambda/package.json 中的"build": "webpack",产物生成在lambda/dist/index.mjs。
  5. 将lambda/dist/index.mjs压缩为.zip文件,供后续上传使用。

后端源码的数据写入实现

打包进函数的业务逻辑在 lambda/src/index.js 中实现:

import { PutCommand } from "@aws-sdk/lib-dynamodb"; import { ddbDocClient } from "./ddbDocClient.js"; export const handler = async (event) => { const params = { Item: { Id: event.Item.Id, Color: event.Item.Color, Pattern: event.Item.Pattern, }, TableName: event.TableName, }; try { console.log("Adding data to dynamodb..."); const data = await ddbDocClient.send(new PutCommand(params)); console.log("Added item:", JSON.stringify(data, null, 2)); } catch (err) { console.error(err); } };

Lambda 直接消费浏览器传来的事件对象:从event.Item中取出Id、Color、Pattern,从event.TableName中取出目标表名,通过PutCommand写入。这里使用的是DynamoDB Document Client(@aws-sdk/lib-dynamodb),相比底层DynamoDBClient,它免去了手动 marshall 的繁琐。

Document Client 的组装细节在 lambda/src/ddbDocClient.js 中:通过DynamoDBDocumentClient.from(ddbClient, translateConfig)从底层客户端派生,其中marshallOptions与unmarshallOptions保持 SDK 默认值(不自动转换空值、不剥离 undefined、数字不包装为字符串)。而底层客户端 lambda/src/ddbClient.js 使用fromCognitoIdentityPool作为凭据提供者——注释说明CognitoIdentityClient({})的空参数构造假定区域已由共享配置文件提供。

第四步:部署 Lambda 函数

在 Lambda 控制台 中完成函数创建与代码上传:

  1. 点击Create function(创建函数)。
  2. Function name填写examplePutItem——README 强调该名称必须与前端 frontend/src/index.js 中的FunctionName完全一致,否则浏览器无法触发。
  3. 展开Change default execution role(更改默认执行角色)区域。
  4. 选择Create a new role from AWS policy templates(从 AWS 策略模板创建新角色)。
  5. 在Role name字段输入角色名,并在策略模板中选择Simple microservice permissions——该模板会为 Lambda 授予访问 DynamoDB 的权限。
  6. 点击Create function创建函数。
  7. 在函数的Code(代码)选项卡中,选择Upload from→.zip file,上传第四步打包好的.zip文件,然后点击Save。

用控制台测试事件验证部署

部署完成后可先在控制台做一次冒烟测试。点击Test,提供如下Event JSON:

{ "Item": { "Id": 1001, "Color": "tangerine", "Pattern": "solid" }, "TableName": "lambda-for-browser" }

如果测试成功,可在 DynamoDB 控制台的lambda-for-browser表中看到Id = 1001的记录。这一步验证了 Lambda 的 IAM 执行角色、表名与字段映射全部正确,为接下来的前端联调扫清障碍。

第五步:打包并运行前端

浏览器端代码必须经过 webpack 打包,才能把浏览器兼容的 AWS SDK for JavaScript 一并产出。前端工程的打包配置 frontend/webpack.config.js 非常简单,仅指定mode: "production",其余交给 webpack 默认行为。

前端配置修改

打开 frontend/src/lambdaClient.js,完成两处替换:

  • IDENTITY_POOL_ID = "IDENTITY_POOL_ID"→ 替换为第一步创建的身份池 ID。
  • REGION = "REGION"→ 替换为承载本示例所有资源的 Region。

该文件的核心逻辑展示了浏览器侧最重要的安全机制——用 Cognito 身份池凭据初始化 Lambda 客户端:

import { LambdaClient } from "@aws-sdk/client-lambda"; import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity"; import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; const IDENTITY_POOL_ID = "IDENTITY_POOL_ID"; const REGION = "REGION"; const lambdaClient = new LambdaClient({ region: REGION, credentials: fromCognitoIdentityPool({ client: new CognitoIdentityClient({ region: REGION }), identityPoolId: IDENTITY_POOL_ID, }), }); export { lambdaClient };

fromCognitoIdentityPool是@aws-sdk/credential-provider-cognito-identity提供的凭据提供者:浏览器无需任何长期密钥,只需提供身份池 ID,SDK 便会自动向 Cognito 换取一组临时安全凭据,并使用这些凭据初始化LambdaClient。

前端交互逻辑

frontend/src/index.js 是页面的核心交互逻辑:

import { InvokeCommand } from "@aws-sdk/client-lambda"; import { lambdaClient } from "./lambdaClient.js"; const myFunction = async () => { const color = document.getElementById("c1").value; const pattern = document.getElementById("p1").value; const id = Math.floor(Math.random() * (10000 - 1 + 1)) + 1; const params = { FunctionName: "examplePutItem", Payload: JSON.stringify({ Item: { Id: id, Color: color, Pattern: pattern, }, TableName: "lambda-for-browser", }), }; try { const data = await lambdaClient.send(new InvokeCommand(params)); alert("Success. Data added to table."); console.log("Success, payload", data); } catch (err) { alert("Oops an error occurred."); console.log("Error", err); } }; window.myFunction = myFunction;

值得注意的细节:

  • 从页面两个下拉框(c1颜色、p1图案)读取用户输入;随机生成 1–10000 的整数作为Id分区键值。
  • 通过lambdaClient.send(new InvokeCommand(params))触发名为examplePutItem的函数,Payload中的Item与TableName结构正是后端handler期望的事件格式,前后端字段契约在这里完成对齐。
  • 函数被挂载到window.myFunction,与页面index.html中按钮的onclick="myFunction();"绑定。页面表单源码可参见 frontend/dist/index.html:颜色下拉框提供 Red、Orange、Yellow、Green、Blue、Indigo、Violet 七种选项,图案下拉框提供 Floral、Modern、Paisley、Plain、Plush、Squares、Stripes 七种选项。

启动与验证

按 README 流程完成前端构建与运行:

  1. 完成lambdaClient.js的两处替换后,cd frontend。
  2. 安装依赖:npm i。
  3. 打包:npm run build(对应 frontend/package.json 中的"build": "webpack")。
  4. 在dist目录启动 HTTP 服务器:npx http-server ./dist。
  5. 浏览器访问服务器地址,选择一种颜色和图案。

  1. 点击Submit提交。

  1. 若插入成功,页面弹出Success. Data added to table.提示;同时可在 DynamoDB 控制台刷新lambda-for-browser表,看到新写入的记录。若失败则弹出Oops an error occurred.,此时应优先检查:IDENTITY_POOL_ID与REGION是否已替换、访客角色是否具备lambda:InvokeFunction权限、Lambda 函数名是否与FunctionName一致、表名是否与TableName一致、以及所有资源是否位于同一区域。

权限模型与安全要点回顾

从源码可以梳理出本示例的三层权限边界,理解它们对排查问题与安全加固都很有帮助:

层级承载者权限内容配置位置
浏览器端Cognito 访客角色lambda:InvokeFunctionIAM 控制台访客角色策略
Lambda 执行Lambda 执行角色DynamoDB 访问(Simple microservice permissions模板)Lambda 创建向导
凭据签发Cognito 身份池为访客签发临时凭据Cognito 控制台身份池设置
  • 浏览器永不接触 DynamoDB 凭据:访客角色仅授权lambda:InvokeFunction,即便前端 SDK 被逆向也无法直接读写数据库。
  • 数据校验后移:所有写入 DynamoDB 的动作发生在 Lambda 内部,后续如需增加输入校验、字段过滤或审计日志,只需修改函数代码,无需改动前端。
  • 资源命名强约束:FunctionName(examplePutItem)、TableName(lambda-for-browser)、Id分区键均被前后端源码硬编码,修改任一处都需同步调整另一端,这也是本示例最常见的故障来源。

清理资源

教程完成后,请在控制台依次删除以下资源,避免持续计费:

  1. 在 Lambda 控制台删除函数examplePutItem。
  2. 在 DynamoDB 控制台删除表lambda-for-browser。
  3. 在 Cognito 控制台删除身份池。
  4. 在 IAM 控制台删除为访客创建的 IAM 角色及为 Lambda 创建的执行角色。

小结

通过本教程,你完成了一个完整的“浏览器 → Cognito 身份池 → Lambda → DynamoDB”跨服务示例:掌握了身份池访客凭据的配置、最小权限 IAM 策略的收紧、Lambda 函数 ESM 打包与上传,以及前端 webpack 打包与联调验证。整个示例的源码、打包配置与测试事件均已包含在 javascriptv3/example_code/cross-services/lambda-for-browser 目录中,可作为后续在浏览器中安全调用 AWS 服务的可复用起点。

  • 示例工程
  • 教程
  • 后端

【免费下载链接】aws-doc-sdk-examples

Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.

项目地址:https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples
点击查看免费下载
上一篇:实用高效电路板查看指南:OpenBoardView完整部署与使用教程
下一篇:特斯拉Model 3/Y CAN总线DBC文件:3步掌握汽车数据解析的终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询