首页 > 解决方案 > 如何创建允许经过身份验证的用户将文件上传到 S3 的 Web 表单?

问题描述

如何创建一个接受用户输入并将授权用户上传到 AWS 的图像文件存储的 Web 应用程序?有权上传文件的用户是 Web 用户,而不是 AWS IAM 用户。理想情况下,他们从带有代表此授权用户的查询参数的 url 访问此 Web。我正在考虑在 S3 中创建一个静态网站,将用户输入和图像文件存储在 S3 存储桶子文件夹中。每个授权用户仅对其自己的子文件夹具有读\写权限。但是,由于 S3 是无服务器的,我需要有关如何使用 lambda 和 API Gateway 或其他 AWS 服务来处理来自 Web 表单的请求并将文件上传到 S3 的详细信息。看来我可以使用 Drupal 或 WordPress Webform 插件来创建 webform 并将文件上传到 S3。在这种情况下,我需要 Drupal\WordPress 的 EC2 实例,而不是 S3 静态网站。我正在寻找有关该项目最佳架构的建议。欢迎任何教程、说明和示例代码。提前致谢。

标签: amazon-web-servicesamazon-s3amazon-ec2

解决方案


这个想法是使用AWS CognitoCognito Federated Identities允许将临时访问令牌出售给经过身份验证的用户。它与 Login With Amazon、Facebook、Google 或任何使用 OpenID 或 SAML 的平台集成。

您的 Single Page Web 应用程序可以通过AWS SDK for Javascript访问 Cognito 。

所以这个想法是在你的网页上提出一个身份验证。我正在使用Login with Amazon或类似产品。您还可以选择使用 Cognito 用户池(Cognito 存储用户配置文件并提供登录、注册、密码恢复等功能)

一旦通过身份验证,您的 Javascript 代码就可以调用refresh()AWS.Config.credentials并传递从上述身份验证步骤收到的访问令牌。 refresh()反过来,将调用 Cognito 的 API 来接收临时和用户特定的访问令牌。

function initializeCognito(access_token) {

            return new Promise((resolve, reject) => {

                // Initialize the Amazon Cognito credentials provider
                AWS.config.region = 'us-east-1'; // Region
                AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                    IdentityPoolId: 'us-east-1:cognito pool id', // < -- insert your cognito pool ID here
                    Logins: {
                        'www.amazon.com': access_token
                    }
                });
                console.log("Calling Cognito to refresh AWS Credentials");

                // get AWS credentials
                AWS.config.credentials.refresh(function (err) {

                    if (err) {
                        console.log("Error when calling Cognito");
                        console.log(err, err.stack);
                        reject(err);
                    } else {
                        console.log("Cognito credenials received ");
                        resolve(AWS.config.credentials);
                    }
                });
            });
        }

完成此操作后,您的其余代码可以调用任何 AWS 开发工具包 API 来调用后端服务,包括 S3、DynamoDB ...

这是 DynamoDB 的示例:


        function insertIntoDDB(profile, text) {
            return new Promise((resolve, reject) => {
                var dynamodb = new AWS.DynamoDB();
                var params = {
                    Item: {
                        "cognitoid": { //hash key
                            S: profile.cognito_id
                        },
                        "userid": {
                            S: profile.user_id
                        },
                        "text": {
                            S: text
                        },
                        "creationtime": { // sort key 
                            N: Math.round(new Date() / 1000).toString()
                        },
                        "expirationtime": { // 1 month later ?
                            N: (Math.round(new Date() / 1000) + (1 * 60 * 60 * 24 * 30)).toString()
                        }
                    },
                    TableName: "my_table"
                };
                dynamodb.putItem(params, (err, data) => {
                    if (err) {
                        console.log("Error when calling DynamoDB");
                        console.log(err, err.stack); // an error occurred
                        reject(err);
                    } else {
                        // console.log(data); // successful response
                        resolve(data);
                    }
                });
            });
        }

AWS 开发工具包为您管理身份验证,如您所见,传递访问密钥和秘密密钥不涉及任何代码。访问密钥和秘密密钥由 Cognito 为该特定用户生成并存储在AWS.config.credential对象中。访问密钥和密钥的范围和时间是有限的。

要限制范围,您可以在 Cognito 控制台上定义 IAM 角色以与经过身份验证的用户关联,授予他们仅访问您的代码所需的服务和操作的权限。此外,S3 和 DynamoDB 允许细粒度权限,允许您限制对存储桶中的特定键(文件夹)或表中的行的写入访问。

您可以在https://alexademo.ninja/skills/myteacher/index.html看到这种技术的实际应用。 我写这个是为了与“我的发音老师”Alexa Skill 一起工作。

还有一个完整的教程将向您展示如何使用适用于 JavaScript 的 AWS 开发工具包将图片从 Web 表单上传到AWS 文档中的 S3 。此代码还利用了 Cognito,它非常接近您想要实现的目标。

使用这种技术,不需要后端服务器。


推荐阅读