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

din*_*eth 92 api client-server ruby-on-rails amazon-s3 amazon-ec2

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

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

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

所以问题:

  • 有没有办法限制用户在发出临时令牌时只访问S3上的某些内容?我怎样才能做到这一点?假设有...说100,000或更多用户.
  • 让iOS设备直接删除这些内容是一个好主意吗?
  • 或者应该让服务器控制所有内容传递(这当然解决了安全性)?这是否意味着我必须在将所有内容下载到连接用户之前将其下载到服务器?
  • 如果你知道rails ......我可以使用paperclip和aws-sdk gems来实现这种设置吗?

对多个问题抱歉,我很欣赏对问题的任何见解.谢谢 :)

ejd*_*sen 113

使用aws-sdk gem,您可以通过调用url_for以下命令获取任何S3对象的临时签名URL :

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
Run Code Online (Sandbox Code Playgroud)

这将为您提供仅在S3中的该对象的签名临时使用URL.它会在20分钟后到期(在此示例中),并且仅对该对象有效.

如果客户端需要大量对象,则需要发出大量已签名的URL.

或者应该让服务器控制所有内容传递(这当然解决了安全性)?这是否意味着我必须在将所有内容下载到连接用户之前将其下载到服务器?

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

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

  • 如果您使用的是aws-sdk-ruby的v2,请注意方法有所不同:http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method (5认同)
  • 谢谢你@ejdyksen.我设计的解决方案恰好使用了(我没有用我的答案更新问题)!所以我的解决方案是为GET请求执行经过身份验证的URL.但是,当用户提供内容时,他使用联合IAM令牌(临时凭证到期)为特定/存储桶/用户/对象名称位置创建资源,并附加策略以允许/ bucket/user/*写访问.因此,系统中的任何用户都不会损害其他用户的内容.好像工作还可以.感谢你的回答. (3认同)
  • @Dennis的重点是该文件不必命中你的服务器.该链接不包含您的AWS凭据.它可能包含`ACCESS_KEY_ID`(我不记得我的头脑),但这并不是一个秘密. (3认同)
  • 用户是否可以看到我的访问密钥?还有密钥(已转换) (2认同)
  • @ejdyksen你是对的,我刚刚验证了URL只包含`AWS_ACCESS_KEY_ID`.我原本以为`AWS_SECRET_ACCESS_KEY`也被显示,但事实并非如此. (2认同)

cha*_*qke 46

以上答案使用旧的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)
Run Code Online (Sandbox Code Playgroud)

其中your_object_key是文件的路径.如果您需要查看,请使用以下内容:

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

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

参考

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