94

我是编写 Rails 和 API 的新手。我需要一些有关 S3 存储解决方案的帮助。这是我的问题。

我正在为用户在 iOS 上使用 Facebook API 登录的 iOS 应用程序编写 API。服务器根据 Facebook 向 iOS 用户发出的令牌验证用户,并发出临时会话令牌。从这一点开始,用户需要下载存储在 S3 中的内容。此内容仅属于用户及其朋友的子集。该用户可以向 S3 添加更多内容,这些内容可以被同一群人访问。我想这类似于将文件附加到 Facebook 群组......

用户可以通过 2 种方式与 S3 交互...将其留给服务器或让服务器发出临时 S3 令牌(不确定此处的可能性),用户可以直接访问 S3 的内容 URL。我发现这个问题在谈论这些方法,但是,它确实过时了(2 年前):关于从 iPhone 应用程序和 S3 上传照片的建筑和设计问题

所以问题:

  • 颁发临时令牌时,是否有办法限制用户仅访问 S3 上的某些内容?我怎样才能做到这一点?假设有……说 100,000 或更多用户。
  • 让iOS设备直接拉出这些内容是个好主意吗?
  • 还是应该让服务器控制所有内容传递(这当然解决了安全问题)?这是否意味着我必须先将所有内容下载到服务器,然后再将其交给连接的用户?
  • 如果您知道 rails... 我可以使用回形针和 aws-sdk gem 来实现这种设置吗?

对多个问题表示歉意,我感谢您对问题的任何见解。谢谢 :)

4

2 回答 2

113

使用aws-sdk gem,您可以通过调用以下方法获取任何 S3 对象的临时签名 url url_for

s3 = AWS::S3.new(
  :access_key_id => 1234,
  :secret_access_key => abcd
)
object = s3.buckets['bucket'].objects['path/to/object']
object.url_for(:get, { :expires => 20.minutes.from_now, :secure => true }).to_s

这将为您提供一个仅用于 S3 中该对象的已签名临时使用 URL。它会在 20 分钟后过期(在这个例子中),它只对那个对象有用。

如果您有很多客户需要的对象,您将需要发布大量签名 URL。

还是应该让服务器控制所有内容传递(这当然解决了安全问题)?这是否意味着我必须先将所有内容下载到服务器,然后再将其交给连接的用户?

请注意,这并不意味着服务器需要下载每个对象,它只需要验证并授权特定客户端访问 S3 中的特定对象。

来自亚马逊的 API 文档: https ://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

于 2012-06-05T17:31:29.877 回答
47

以上答案使用旧的 aws-sdk-v1 gem 而不是新的 aws-sdk-resources 版本 2。

新方法是:

aws_resource = Aws::S3::Resource::new
aws_resource.bucket('your_bucket').object('your_object_key').presigned_url(:get, expires_in: 1*20.minutes)

其中 your_object_key 是文件的路径。如果你需要查看它,你会使用类似的东西:

s3 = Aws::S3::Client::new
keys = []
s3.list_objects(bucket: 'your_bucket', prefix: 'your_path').contents.each { |e| 
  keys << e.key
}

这些信息非常难以挖掘,我几乎放弃并使用了较旧的宝石。

参考

http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method

于 2015-07-10T18:58:23.960 回答