我想通过rails app保护我的s3文件,以便我去:
www.myapp.com/attachment/5应在显示/下载文档之前对用户进行身份验证。
我已经在stackoverflow上读过类似的问题,但我不确定我是否看到了任何好的结论。
根据我的阅读,您可以采取一些措施来“保护”您的S3文档。
1)模糊URL。我做到了这一点。我认为这是一件好事,所以没有人可以猜到这个网址。例如,如果你的S3网址很明显,那么很容易“走”网址:https://s3.amazonaws.com/myapp.com/attachments/1/document.doc。拥有以下URL: https://s3.amazonaws.com/myapp.com/7ca/6ab/c9d/db2/727/f14/document.doc似乎好多了。 这很好,但无法解决通过电子邮件或网站传递URL的问题。
2)使用过期网址,如下所示:Rails 3, paperclip + S3 - Howto Store for an Instance and Protect Access 对我来说,这不是一个很好的解决方案,因为URL是公开的(即使只是很短的一段时间),另一个用户也许可以及时重用URL。您必须调整允许下载的时间,而不会提供太多的复制时间。这似乎是错误的解决方案。
3)通过应用程序代理文档下载。起初我尝试使用send_file:http://www.therailsway.com/2009/2/22/file-downloads-done-right,但问题是这些文件只能是服务器上的静态/本地文件,而不是通过其他站点(S3 / AWS)提供。但是,我可以使用send_data并将文档加载到我的应用程序中,并立即将文档提供给用户。这个解决方案的问题很明显 - 带宽的两倍和时间的两倍(将文档加载到我的应用程序然后再返回给用户)。
我正在寻找一种能够提供#3完全安全性的解决方案,但不需要额外的带宽和时间来加载。看起来Basecamp正在“保护”他们应用程序背后的文档(通过身份验证),我认为其他网站正在做类似的事情,但我不认为他们正在使用我的#3解决方案。
建议将不胜感激。
更新:
我选择了第四个解决方案:
4)使用amazon存储桶策略根据引用来控制对文件的访问: http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?UsingBucketPolicies.html
再次更新
#4井可以通过浏览器开发人员的工具轻松解决。所以我仍然在寻找一个可靠的解决方案。
答案 0 :(得分:1)
您想做两件事:
将存储桶及其中的所有对象设为私有。命名约定实际上并不重要,越简单越好。
生成签名的URL,然后从您的应用程序重定向到它们。这样,您的应用可以检查用户是否已通过身份验证和授权,然后生成一个新的签名URL,并使用301 HTTP状态代码将其重定向到该URL。这意味着该文件将永远不会通过您的服务器,因此您没有负载或带宽。以下是用于预签GET_OBJECT请求的文档:
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Presigner.html
答案 1 :(得分:0)
我会投票给3号,这是唯一真正安全的方法。因为一旦您将用户传递到有效期至其到期时间的S3 URL。一个狡猾的用户可以使用那个洞,唯一的问题是,这会影响你的应用程序吗? 也许您可以将过期时间设置得更低,从而将风险降至最低? 看一下这篇文章的摘录: Accessing private objects from a browser
可以通过访问所有私有对象 对S3的经过身份验证的GET请求 服务器。你可以生成一个 经过身份验证的URL,用于对象 这样:
S3Object.url_for('beluga_baby.jpg', 'marcel_molina')
默认情况下 经过身份验证的网址将在5分钟后过期 它们产生后。
可以指定过期选项 自从以来的绝对时间 epoch与:expires选项,或 相对于数秒钟 现在使用:expires_in选项:
答案 2 :(得分:0)
我一直在尝试做类似的事情已经有一段时间了。如果您不想两次使用带宽,那么唯一可行的方法是允许S3执行此操作。现在我完全了解了暴露的URL。你能想出任何替代方案吗?
我发现在这方面可能有用的东西 - http://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempFederationTokenRuby.html
用户登录后,应创建一个aws会话,其IP作为aws策略的一部分,然后可用于生成签名的URL。因此,如果其他人抓住URL,签名将不匹配,因为请求的来源将是不同的IP。让我知道这是否有意义并且足够安全。