Amazon web services 如何使用AWS Cognito限制对S3文件的访问?

Amazon web services 如何使用AWS Cognito限制对S3文件的访问?,amazon-web-services,amazon-s3,amazon-cognito,pre-signed-url,Amazon Web Services,Amazon S3,Amazon Cognito,Pre Signed Url,我正在创建一个web应用程序,它需要从S3存储桶向用户提供大文件以供下载。我们应用程序中的用户由Cognito授权。我希望有一个包含文件的S3存储桶,这样某些Cognito用户只允许下载某些文件。从我的研究中,我找到了一些方法。就我所知,所有这些似乎都不完全适合我的用例 AWS允许由Cognito用户许可S3存储桶。这是如此接近我需要的,但实际上似乎不可用。在我们应用程序的安全方案中,Cognito登录属于一个组织。每个组织都在后端共享其所有数据。因此,我需要允许我的数据库访问权限定义的组织中的

我正在创建一个web应用程序,它需要从S3存储桶向用户提供大文件以供下载。我们应用程序中的用户由Cognito授权。我希望有一个包含文件的S3存储桶,这样某些Cognito用户只允许下载某些文件。从我的研究中,我找到了一些方法。就我所知,所有这些似乎都不完全适合我的用例

AWS允许由Cognito用户许可S3存储桶。这是如此接近我需要的,但实际上似乎不可用。在我们应用程序的安全方案中,Cognito登录属于一个组织。每个组织都在后端共享其所有数据。因此,我需要允许我的数据库访问权限定义的组织中的所有登录到S3存储桶,而不是按名称登录的用户

在某种程度上,预先签名的URL似乎是这方面的典型用例,但我认为这并不是我真正需要的。预签名的URL将为用户提供一个过期的URL以下载文件。很好,所以我可以给每个用户一个URL,该URL可能是用户自定义的,但我可以在后端发布几个URL。但我真的不希望URL过期,我希望它能永远持续下去。这不是什么大问题,因为永久URL可能是一个API端点,可以重定向到动态创建的预签名URL,该URL可能在一分钟内过期。但这个URL将允许任何拥有它的人访问。这不符合我们通过登录将URL限制为Cognito用户的安全模型。如果该URL通过用户剪切和粘贴或数据包嗅探器泄露出去,则安全性似乎会崩溃。确实URL过期了,但它似乎并不完全适合此项目

我考虑过的另一个选项是通过创建API端点在代码中实现这一点,该端点创建了一个可下载的文件流,该文件流也是通过访问S3对象作为文件流创建的。它将把文件读入内存并将其流式传输给用户。这方面的安全性似乎完全符合我们的需要,因为API端点当然会验证Cognito用户的身份验证令牌。但是从S3存储桶读取到我的后端,然后发送给用户是不必要的网络流量,可能会更慢,并且在后端过程中可能需要大量内存


似乎最好的解决方案是省去中间人,允许用户直接访问S3存储桶,尽管有正确的用户权限限制。我只是可以找到任何项目或教程,这样做的最佳实践推荐的方式,适合我的项目。我认为我的项目有一个非常常见的用例。有没有更好的方法来解决这个问题?

我见过应用程序解决这个问题的一种方法是只使用一个带有不可用S3对象名的完全公共存储桶。例如,您可以将用户文件存储在
s3://public bucket/
中,然后在响应中将它们重定向到该对象的公共URL,这样用户就可以直接从s3下载。由于S3不允许您列出对象,因此从理论上讲,这是安全的,因为对象的随机名称类似于密码,访问文件时需要确切知道密码。而且,由于到S3的所有通信都是通过SSL进行的,所以在传输过程中永远不能公开URL

就我个人而言,这让我觉得有点恶心,因为与密码不同,文件名在浏览器历史记录和其他地方都是可见的,但如果数据不太敏感,这可能不是世界上最糟糕的事情

你提到的一件事我不同意:

我考虑过的另一个选择是自己在代码中实现这一点 制作一个API端点,创建一个可下载的文件流 通过作为文件流访问S3对象来创建。 ... 但是从S3存储桶读取数据到后端,然后转到 用户是不必要的网络流量,可能会较慢,而且还需要 后端进程中可能存在大量内存

在我看来,这可能是最好的解决方案(使用Web服务器作为中介),因为您可以完全控制您的应用程序逻辑,并且可以在知道不太可能出现恶作剧和数据泄露的情况下安然入睡


我非常怀疑它在计算上会有很多开销。通过S3的数据流传输应该是快速的,并且使用很少的内存(您可能可以在
t2.micro上执行此操作,除非您有大量的请求,否则不会有问题)。所有的web框架都应该允许您在HTTP响应中流式传输数据,所以您根本不需要将数据流存储到内存中。我已经构建了类似的东西,而且它从来都不是我的性能瓶颈。

我见过应用程序解决这个问题的一种方法就是使用一个带有不可用的S3对象名的完全公共的bucket。例如,您可以将用户文件存储在
s3://public bucket/
中,然后在响应中将它们重定向到该对象的公共URL,这样用户就可以直接从s3下载。由于S3不允许您列出对象,因此从理论上讲,这是安全的,因为对象的随机名称类似于密码,访问文件时需要确切知道密码。而且,由于到S3的所有通信都是通过SSL进行的,所以在传输过程中永远不能公开URL

就我个人而言,这让我觉得有点恶心,因为与密码不同,文件名在浏览器历史记录和其他地方都是可见的,但如果数据不太敏感,这可能不是世界上最糟糕的事情

你提到的一件事我不同意:

我考虑过的另一个选择是自己在代码中实现这一点 制作一个API端点,创建一个可下载的文件流 通过作为文件流访问S3对象来创建。 ... 但是从S3存储桶读取数据到后端,然后转到 用户是不必要的网络流量,可能会较慢,而且还需要