7

这是一个故事:

  • 用户 A 应该能够上传图像。
  • 用户 A 应该能够设置隐私。(“公共”或“私人”)。
  • 用户 B 应该无法访问用户 A 的“私人”图像。

我打算使用Paperclip来处理上传。

如果我将图像存储在“RAILS_ROOT/public/images”下,任何能猜出文件名的人都可以访问这些文件。(例如,访问http://example.com/public/images/uploads/john/family.png

我需要使用img标签显示图像,所以我不能放置除public.

如何确保其他人无法访问用户或组的图像?

(如果我不能用回形针实现这一点,有什么好的解决方案?)

4

4 回答 4

9

你可以让你的 Rails 服务器输出图像文件的内容。这是通过控制器操作完成的(例如,大多数操作打印 HTML,但这个操作将打印 JPG)。

然后您可以使用您的授权系统来限制控制器级别的访问!

class ImagesController
  #Default show Image method streams the file contents.
  #File doesn't have to be in public/ dir
  def show
    send_file @image.filename, :type => @image.content_type,
              :disposition => 'inline'
  end

  # Use your favorite authorization system to restrict access
  filter_access_to :show, :require => :view, :attribute_check => :true
end

在 HTML 代码中,您可以使用:

<img src="/images/show/5" />
于 2010-05-02T05:56:37.607 回答
5

我会让 Paperclip 在后端使用 S3,将上传的文件设置为私有,然后使用“Query String Request Authentication Alternative”为我的图像标签生成 URL。

http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

于 2010-05-02T06:29:15.817 回答
5

以下是我在类似应用程序中的做法。

  • 将您的图像存储在 Amazon S3 而不是本地文件系统上。回形针支持这一点。
  • 在回形针选项中将 :s3_permissions 设置为“私有”
  • 在您的图像模型中,定义一个方法,让您为图像输出一个授权的、有时间限制的 url。

我的看起来像这样:

def s3_url(style = :original, time_limit = 30.minutes)
  self.attachment.s3.interface.get_link(attachment.s3_bucket.to_s, attachment.path(style), time_limit)
end
  • 然后,只有在获得授权的情况下,您才能向人们显示图像(以您喜欢的方式实施),而不必担心人们猜测/查看私人图像。它还可以防止它们在 URL 过期后传递它们(URL 中有一个令牌)。
  • 请注意,您的应用需要时间来为每张图片生成授权网址。因此,如果您的页面上有多个图像,则会影响加载时间。
于 2010-05-02T06:33:44.883 回答
1

如果您想自己托管文件,可以按照建议在控制器级别执行身份验证。例如,我的一个应用程序有一个 AssetController 来处理“私人”目录中的文件服务。

我想补充的一件事是,您应该查看本指南以设置 X-Sendfile,这将使您的应用程序告诉 Web 服务器处理实际发送文件。使用这种方法,您会看到更好的性能。

于 2012-10-18T15:42:59.947 回答