ruby-on-rails – 保护Rails应用中的公开内容

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

在我们开始撰写之前,如果有人遇到这样的问题,我很好奇?我寻找一些可能已经这样做但没有找到任何东西的宝石/插件.有没有人为此创造了宝石?

我在一个人们付费下载某些文件的网站上完成了这些操作,文件存储在RAILS_ROOT / private中.首先要知道的是,您希望Web服务器处理发送文件,否则您的应用程序将被阻止传输大文件,如果您有任何下载量,这将很快使您的站点停止.因此,如果您需要在控制器中检查授权,那么您还需要一种方式将下载的控制权传回到Web服务器.这样做的最好的方法(我知道的)是Nginx,Apache(与模块)等支持的X-Sendfile头文件.配置X-Sendfile时,当您的Web服务器从应用程序接收到X-Sendfile头文件时,它会将文件发送给客户端.

一旦X-Sendfile为您的Web服务器工作,这样一个私人控制器方法是有帮助的:

##
# 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

那么你的控制器操作可能看起来像这样:

##
# 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

显然,您的授权方法会有所不同,如果您提供PDF以外的其他文件,或者您希望在浏览器中查看文件(摆脱应用程序/强制下载内容类型),则需要更改标题.

翻译自:https://stackoverflow.com/questions/2143300/protecting-the-content-of-public-in-a-rails-app

转载注明原文:ruby-on-rails – 保护Rails应用中的公开内容