Rails 3,回形针 + S3 - 如何存储实例并保护访问 [英] Rails 3, paperclip + S3 - Howto Store for an Instance and Protect Access

查看:35
本文介绍了Rails 3,回形针 + S3 - 如何存储实例并保护访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有回形针的 Rails 3 应用程序,目的是将数据存储在 S3 上.

在应用中,用户属于一个实例.

我希望每个实例的所有模型都存储数据.并希望阻止来自实例 A 的用户访问,或能够从实例 B 加载数据.

处理这个问题的最佳方法是什么?谢谢

解决方案

我实际上只是在我的 Ruby on Rails 3 应用程序中使用 Paperclip 实现了授权的 S3 url.让我分享一下我是如何做到这一点的.

所以我所做的以及您可能想要的很容易实现.我给你举个例子:

文件对象模型

has_attached_file :attachment,:路径=>"files/:id/:basename.:extension",:存储 =>:s3,:s3_permissions =>:私人的,:s3_credentials =>File.join(Rails.root, 'config', 's3.yml')

FileObjectsController 控制器

 定义下载@file_object = FileObject.find(params[:id])redirect_to(@file_object.attachment.expiring_url(10))结尾

我相信这很简单.您将回形针附件添加到 FileObject 模型,然后在 FileObjectsController 中有一个操作(例如下载).通过这种方式,您可以使用 before_filter 或其他东西从您的控制器中进行一些应用程序级别的授权.

@file_object.attachment 上的 expiring_url() 方法(由 Paperclip 提供)基本上向 Amazon S3 请求一个密钥,该密钥使可使用该特定密钥访问的文件.expiring_url() 方法的第一个参数采用一个整数,表示您希望提供的 URL 过期的.

在我的应用程序中,它当前设置为 10 (@file_object.attachment.expiring_url(10)) 所以当用户请求一个文件时,用户总是必须通过我的应用程序例如 myapp.com/file_objects/3/download 从亚马逊获取一个新的有效 URL,然后用户将立即使用它来下载文件,因为我们使用的是下载 操作中的 redirect_to 方法.因此,基本上在用户点击 下载 操作 10 秒后,链接已经过期并且用户已经(或仍在)愉快地下载文件,同时它仍然受到任何非授权用户的保护.>

我什至尝试设置 expiring_url(1) 以便在用户触发对 URL 的 Amazon S3 请求后 URL 立即过期.这在本地对我有用,但从未在生产中使用过,您也可以尝试一下.但是,我将其设置为 10 秒,以便让服务器在短时间内做出响应.到目前为止效果很好,我怀疑有人会在 URL 创建后 10 秒内劫持它,更不用说知道 URL 是什么了.

我采取的额外安全措施只是为创建的每个文件生成一个密钥,因此我的 URL 始终如下所示:

has_attached_file :attachment,:路径=>文件/:id/:secret_key/:basename.:extension"

这样每个 URL 在其路径中都有唯一的 secret_key,从而在 URL 可访问的时间内更难劫持.请注意,虽然文件的 URL 保持不变,但可访问性来自 Amazon S3 提供的其他过期参数:

http://s3.amazonaws.com/mybucket/files/f5039a57acc187b36c2d/my_file.pdf?AWSAccessKeyId=AKIAIPPJ2IPWN5U3O1OA&Expires=1288526454&Signature=92PhnD/SHP

注意这部分,这是亚马逊生成并过期的密钥,它使文件暂时可访问:

my_file.pdf?AWSAccessKeyId=AKIAIPPJ2IPWN5U3O1OA&Expires=1288526454&Signature=5i4%2B99rUwhpP2SbNsJKhT/nSzsQ%3D

就是这样.如果通过下载操作请求,这会随着对您文件的每个请求而改变.

希望这有帮助!

I have a Rails 3 app with paperclip, with the intent to store data on S3.

In the app, Users belong to an instance.

I would like the data stored across all the models per instance. And would like to prevent a user from Instance A from accessing, or being able to load data from Instance B.

What's the best way to handle this? thanks

解决方案

I actually just implemented authorized S3 url's in my Ruby on Rails 3 application with Paperclip. Let me share how I accomplished this.

So what I did, and what you probably want is quite easy to implement. Let me give you an example:

FileObject model

has_attached_file :attachment,
  :path           => "files/:id/:basename.:extension",
  :storage        => :s3,
  :s3_permissions => :private,
  :s3_credentials => File.join(Rails.root, 'config', 's3.yml')

FileObjectsController controller

  def download
    @file_object = FileObject.find(params[:id])
    redirect_to(@file_object.attachment.expiring_url(10))
  end

I believe this is quite straightforward. You add the Paperclip attachment to the FileObject model and then have an action (download for example) in the FileObjectsController. This way you can do some application level authorization from within your controller with a before_filter or something.

The expiring_url() method (provided by Paperclip) on the @file_object.attachment basically requests Amazon S3 for a key which makes the file accessible with that particular key. The first argument of the expiring_url() method takes an integer which represents the amount of seconds in which you want the provided URL to expire.

In my application it is currently set to 10 (@file_object.attachment.expiring_url(10)) so when the user requests a file, the user ALWAYS has to go through my application at for example myapp.com/file_objects/3/download to get a new valid URL from Amazon, which the user then instantly will be using to download the file since we're using the redirect_to method in the download action. So basically 10 seconds after the user hits the download action, the link already expired and the user has (or is still) happily downloading the file, while it remains protected from any non-authorized users.

I have even tried to set expiring_url(1) so that the URL instantly expires after the user triggers the Amazon S3 request for the URL. This worked for me locally, but never used it in production, you can try that too. However, I set it to 10 seconds to give the server a short period of time to respond. Works great so far and I doubt anyone will hijack someone's URL within 10 seconds after it's been created, let alone know what the URL is.

Extra security measure I took is just to generate a secret key for every file on create so my URL's always look like this:

has_attached_file :attachment,
  :path => "files/:id/:secret_key/:basename.:extension"

So that every URL has it's unique secret_key in it's path, making it harder to hijack within the time the URL is accessible. Mind you that, while the URL to your file remains the same, the accessibility comes from the additional parameters that Amazon S3 provides which expire:

http://s3.amazonaws.com/mybucket/files/f5039a57acc187b36c2d/my_file.pdf?AWSAccessKeyId=AKIAIPPJ2IPWN5U3O1OA&Expires=1288526454&Signature=5i4%2B99rUwhpP2SbNsJKhT/nSzsQ%3D

Notice this part, which is the key Amazon generates and expires which makes the file temporarily accessible:

my_file.pdf?AWSAccessKeyId=AKIAIPPJ2IPWN5U3O1OA&Expires=1288526454&Signature=5i4%2B99rUwhpP2SbNsJKhT/nSzsQ%3D

That's what it's all about. And this changes with every request for your file if requested through the download action.

Hope this helps!

这篇关于Rails 3,回形针 + S3 - 如何存储实例并保护访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆