如何创建允许经过身份验证的用户将文件上传到S3的Web表单?

时间:2019-01-17 23:05:14

标签: amazon-web-services amazon-s3 amazon-ec2

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

2 个答案:

答案 0 :(得分:1)

如果您要求用户对您的应用程序进行身份验证,则需要将其凭据存储在某个数据库(即DynamoDB)中。为此,您需要一些将执行身份验证过程的后端服务-将用户的凭据存储在数据库中,从数据库中检索用户的凭据,然后验证凭据。

您可以编写自己的服务器,也可以通过API Gateway使用无服务器Lambda方法。但是这里重要的是,您需要具有此后端逻辑。无法仅使用静态S3虚拟主机来实现它(但它可以成为整个系统的一部分)。

在这种情况下,仅使用AWS IAM创建角色,该角色允许服务EC2 / Lambda对S3存储桶和DynamoDB执行读/写操作。您的应用程序用户与IAM无关。

应用程序的流程为:

  1. 用户注册您的应用程序
  2. 您的应用程序使用用户凭据和指向该用户唯一的某些S3资源的指针在数据库中创建一条记录
  3. 登录的用户尝试上传图片时,数据将发送到您的应用程序
  4. 您的应用程序从数据库中检索请求者的记录,查找S3指针并将图像上传到那里

从体系结构的角度来看,在设计这样的系统时要考虑很多因素-流量,对CI-CD的要求等等。

如果您想简单一些,则可以使用API​​网关创建REST API,其中每个资源方法都将分配有适当的lambda函数(这些函数将执行上述逻辑)。您可以使用自定义身份验证流程,也可以利用AWS Congnito。最后,您可以在S3上托管网页(假设在此设置中它是静态的),并针对API网关进行Ajax调用。

答案 1 :(得分:1)

想法是使用AWS CognitoCognito Federated Identities允许向经过身份验证的用户出售临时访问令牌。它与Login With Amazon,Facebook,Google或任何使用OpenID或SAML的语言集成。

您的单页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允许使用fine grained permission,从而允许您限制对存储桶或表中行中特定键(文件夹)的写访问。

您可以在https://alexademo.ninja/skills/myteacher/index.html看到此技术的实际效果,我将其写为与“ My Pronunciation Teacher” Alexa Skill一起使用。

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

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