Ruby-on-rails 如何在 S3 中存储数据并允许用户使用 Rails API / iOS 客户端以安全的方式访问?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10811017/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:28:13  来源:igfitidea点击:

How to store data in S3 and allow user access in a secure way with rails API / iOS client?

ruby-on-railsapiamazon-s3amazon-ec2client-server

提问by dineth

I am new to writing Rails and APIs. I need some help with S3 storage solution. Here's my problem.

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

I am writing an API for an iOS app where the users login with the Facebook API on iOS. The server validates the user against the token Facebook issues to the iOS user and issues a temporary Session token. From this point the user needs to download content that is stored in S3. This content only belongs to the user and a subset of his friends. This user can add more content to S3 which can be accessed by the same bunch of people. I guess it is similar to attaching a file to a Facebook group...

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

There are 2 ways a user can interact with S3... leave it to the server or get the server to issue a temporary S3 token (not sure of the possibilities here) and the user can hit up on the content URLs directly to S3. I found this question talking about the approaches, however, it is really dated (2 yrs ago): Architectural and design question about uploading photos from iPhone app and S3

用户可以通过 2 种方式与 S3 交互……将其留给服务器或让服务器发出临时 S3 令牌(不确定此处的可能性),并且用户可以直接访问 S3 的内容 URL。我发现这个问题在谈论这些方法,但是,它确实过时了(2 年前):Architectural and design question about uploading photos from iPhone app and S3

So the questions:

所以问题:

  • Is there a way to limit a user to access only some content on S3 when a temporary token is issued? How can I do this? Assume there's... say 100,000 or more users.
  • Is it a good idea to let the iOS device pull this content out directly?
  • Or should let the server control all content passing (this solves security of course)? Does this mean I have to download all content to server before handing it down to the connected users?
  • If you know rails... can I use paperclip and aws-sdk gems to achieve this kinda setup?
  • 有没有办法限制用户在颁发临时令牌时只能访问 S3 上的某些内容?我怎样才能做到这一点?假设有...说 100,000 或更多的用户。
  • 让 iOS 设备直接拉出这个内容是个好主意吗?
  • 还是应该让服务器控制所有的内容传递(这当然可以解决安全问题)?这是否意味着我必须将所有内容下载到服务器,然后才能将其传递给连接的用户?
  • 如果你知道 rails ......我可以使用回形针和 aws-sdk gems 来实现这种设置吗?

Apologies for multiple questions and I appreciate any insight into the problem. Thanks :)

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

回答by ejdyksen

Using the aws-sdk gem, you can get a temporary signed url for any S3 object by calling url_for:

使用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

This will give you a signed, temporary use URL for only that object in S3. It expires after 20 minutes (in this example), and it's only good for that one object.

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

If you have lots of objects the client needs, you'll need to issue lots of signed URLs.

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

Or should let the server control all content passing (this solves security of course)? Does this mean I have to download all content to server before handing it down to the connected users?

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

Note that this doesn't mean the server needs to download each object, it only needs to authenticate and authorize specific clients to access specific objects in S3.

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

API docs from Amazon: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

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

回答by chaqke

The above answers use the old aws-sdk-v1 gem rather than the new aws-sdk-resources version 2.

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

The new way is:

新方法是:

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

where your_object_key is the path to your file. If you need to look that up, you would use something like:

其中 your_object_key 是文件的路径。如果您需要查找它,您可以使用以下内容:

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

That information was startlingly difficult to dig up, and I almost just gave up and used the older gem.

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

Reference

参考

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

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