安全地显示上传了paperclip gem的图像

时间:2016-01-11 01:29:51

标签: ruby-on-rails ruby paperclip pundit

默认情况下:paperclip gem将所有附件存储在公共目录中。

出于安全原因,我不想将附件存储在公共目录中,因此我将它们保存在应用程序根目录的uploads目录中:

class Post < ActiveRecord::Base
  belongs_to :user

  has_attached_file :some_image, path: ":rails_root/uploads/:attachment/:id/:style/:filename"
  do_not_validate_attachment_file_type :some_image
end

我没有指定url选项,因为我不想为每个图片附件添加网址。如果指定了url:那么具有该url的任何人都可以访问该图像。这不安全。

user#show页面中:我想实际显示图片。如果我使用了所有的回形针默认设置,那么我可以这样做,因为图像将在公共目录中,而图像一个网址:

<p>
  <strong>Some image:</strong>
  <%= image_tag @post.some_image %>
</p>

如果我将图像附件保存在公共目录之外并且未指定网址(再次:执行此操作以保护图像),则该图像将无法在视图中呈现。

我知道如何通过pundit gem在整个应用程序中进行授权。但是,当该图像可公开访问时,授权图像是无用的。因此,我尝试通过删除URL并将图像保存在公共目录之外来使图像无法公开访问,但随后图像不再在视图中呈现。

更新:我的问题实际上归结为:我的图片保存在我的rails应用程序中。使用回形针:有没有办法在视图中安全地显示图像?换句话说:设置它使图像没有自己独立的URL(因为任何有该URL的人都可以访问该图像,使该图像不安全)。以下是安全显示图像的一些示例:

  • 示例#1:仅在用户登录时显示图像。(图像没有自己独立的网址,因此没有其他方式可以访问图像)
  • 示例#2:仅在用户与此图像关联时才显示图像。 (图像没有自己独立的网址,因此没有其他方法可以访问图像)

其他更新:我知道我可以安全地发送一个send_file文件,允许用户下载图片,但这不是我想要做的。我不希望用户下载图像。相反:我希望用户能够在网页上实际 查看 图片。我想安全 显示/渲染 页面上的图片。使用send_file(据我所知)允许用户下载文件。它不会在页面上呈现图像。

3 个答案:

答案 0 :(得分:9)

您可以使用send_file。假设您的路线中有secure_image个操作:

resources :posts do
  member do
    get :secure_image
  end
end

以及相应控制器中的以下方法:

def secure_image
  send_file Post.find(params[:id]).some_image.path
end

您可以在视图中使用受保护的图片:

<%= image_tag secure_image_post_path(@post) %>

这里发生了什么:通常Rails(或nginxapache)为了速度而直接绕过安全检查发送静态文件。但secure_image行动请求通过整个Rails&#39;堆栈,因此它受您的身份验证系统保护。

答案 1 :(得分:1)

您可以在其中一个Rails控制器中执行操作,以验证用户的身份/权限以查看图像。然后,操作可以使用send_file

在其http响应中发送图像,而不是呈现视图

http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_file

然后,一旦您自己开始执行该操作,并且可以看到它在浏览器中显示图像,您就可以制作指向该操作的网址的img标记。

每个图片都有自己的网址,但您可以完全控制该网址是什么以及谁可以访问它。

答案 2 :(得分:0)

您可以将图像转换为Base64格式,而显示可以将图像转换为图像。

其他技巧是为您的图像添加水印,以确保图像对其他人无用。