ruby 如何在Rails应用中保护public/的内容

njthzxwz  于 2023-04-20  发布在  Ruby
关注(0)|答案(5)|浏览(143)

我正在维护一个Rails应用程序,它在public/文件夹中包含内容,现在需要通过登录来保护。我们正在考虑将这些文件夹移动到public/之外的路径中,并编写一个Rails控制器来提供内容。
在我们开始写这篇文章之前,我很好奇是否有人遇到过这种问题?我寻找了一些可能已经做到这一点的gem/插件,但没有找到任何东西。有人为此创建了一个gem吗?

uemypmqf

uemypmqf1#

我在一个网站上做了这个,人们付费下载某些文件,文件存储在RAILS_ROOT/private中。首先要知道的是,你希望Web服务器处理发送文件,否则你的应用程序将无法传输大文件,如果你有任何类型的下载量,这将很快使你的网站停止。所以,如果你需要在控制器中检查授权,然后你还需要一种方法来将下载的控制权传递回Web服务器。(据我所知)最好的方法是X-Sendfile头,Nginx,Apache(带模块)和其他人都支持它。配置了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以外的文件,或者您希望在浏览器中查看文件(摆脱application/force-download内容类型),则需要更改标题。

6g8kf2rb

6g8kf2rb2#

你可以使用Amazon S3。你可以使用控制器来生成和提供你的安全区域后面的URL,它还有一个功能,基本上是在生成URL后,资源只在一定的时间内可用。
看看这个URL:http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

f87krz0w

f87krz0w3#

AFAIK,Nginx不支持X-SendFile。Nginx有自己的扩展允许这种情况,称为X-Accel-Redirect。
您将在这里找到有关此的更多信息:https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
在github上也有一个rails插件实现了这个功能:goncalossilva/X-Accel-Redirect

q35jwt9p

q35jwt9p4#

如果您希望将内容交付与Rails身份验证和授权系统绑定在一起,那么您必须将内容置于控制器之后。
如果您正在寻找更简单的登录方法,您可以在托管环境中使用HTTP Auth和设置(例如使用htaccess)来处理它。

nmpmafwu

nmpmafwu5#

使文件在不可预测的URL上可用是当前在某些生产系统中使用的简单解决方案。

例如:GitLab。下面的图片被上传到一个私有仓库的问题,https://gitlab.com/cirosantilli/test-private/issues/1,但你仍然可以看到它:

注意自动添加到URL的难以猜测的90574279de前缀。
Bitbucket(非Rails)也使用这种技术。

相关问题