保护Rails应用程序中的public/content内容

Mat*_*ins 17 ruby protection ruby-on-rails public

我正在维护一个Rails应用程序,其中包含公共/文件夹中的内容,现在需要通过登录进行保护.我们正在考虑将这些文件夹移动到public/public之外的路径中,并编写Rails控制器来提供内容.

在我们开始写这篇文章之前,我很好奇是否有其他人遇到过这类问题?我找了一些可能已经这样做但没有找到任何东西的宝石/插件.有没有人为此创造了一个宝石?

Ale*_*ner 16

我在人们为下载某些文件而付费的网站上完成了这项工作,并将文件存储在其中RAILS_ROOT/private.首先要知道的是,您希望Web服务器处理发送文件,否则您的应用程序将被阻止传输大文件,如果您有任何类型的下载量,这将很快使您的网站停止运行.因此,如果您需要检查控制器中的授权,那么您还需要一种方法将下载控制权传递回Web服务器.执行此操作(我知道)的最佳方法是X-Sendfile标头,它由Nginx,Apache(带模块)和其他人支持.配置X-Sendfile后,当您的Web服务器X-Sendfile从您的应用程序收到标头时,它会接管将文件发送到客户端.

一旦你的Web服务器使用X-Sendfile,这样的私有控制器方法是有帮助的:

##
# Send a protected file using the web server (via the x-sendfile header).
# Takes the absolute file system path to the file and, optionally, a MIME type.
#
def send_file(filepath, options = {})
  options[:content_type] ||= "application/force-download"
  response.headers['Content-Type'] = options[:content_type]
  response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filepath)}\""
  response.headers['X-Sendfile'] = filepath
  response.headers['Content-length'] = File.size(filepath)
  render :nothing => true
end
Run Code Online (Sandbox Code Playgroud)

然后您的控制器操作可能如下所示:

##
# Private file download: check permission first.
#
def download
  product = Product.find_by_filename!(params[:filename])
  if current_user.has_bought?(product) or current_user.is_superuser?
    if File.exist?(path = product.filepath)
      send_file path, :content_type => "application/pdf"
    else
      not_found
    end
  else
    not_authorized
  end
end
Run Code Online (Sandbox Code Playgroud)

显然,您的授权方法会有所不同,如果您提供的文件不是PDF,或者您希望在浏览器中查看文件(删除application/force-download内容类型),则需要更改标题.

  • 为什么这不使用内置的send_file方法? (5认同)
  • 因为我不知道它!使用这种技术的任何人都应该删除我残缺的`send_file`方法定义,而是调用包含Rails的`send_file路径,:type =>"application/pdf",:x_sendfile => true`.谢谢你,Ryan. (3认同)

Dou*_*g R 2

您可以使用亚马逊 S3。您可以使用控制器生成并提供安全区域后面的 url,它还有一个功能,基本上是在生成 url 后,资源仅在一定时间内可用。

查看此网址:http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html ?RESTAuthentication.html