我正在维护一个 Rails 应用程序,该应用程序在 public/ 文件夹中包含现在需要通过登录来保护的内容。我们正在考虑将这些文件文件夹移动到 public/ 之外的路径中,并编写一个 Rails 控制器来提供内容。
在我们开始写这篇文章之前,我很好奇是否有其他人遇到过这种问题?我寻找了一些可能已经这样做但没有找到任何东西的宝石/插件。有没有人为此创造了一个宝石?
我正在维护一个 Rails 应用程序,该应用程序在 public/ 文件夹中包含现在需要通过登录来保护的内容。我们正在考虑将这些文件文件夹移动到 public/ 之外的路径中,并编写一个 Rails 控制器来提供内容。
在我们开始写这篇文章之前,我很好奇是否有其他人遇到过这种问题?我寻找了一些可能已经这样做但没有找到任何东西的宝石/插件。有没有人为此创造了一个宝石?
我在一个人们付费下载某些文件的网站上完成了这项工作,这些文件存储在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
内容类型),则需要更改标题。
您可以使用 Amazon S3。您可以使用控制器在您的安全区域后面生成和提供 url,它还有一个功能,即一旦生成 url,资源基本上只在一定时间内可用。
查看此网址:http ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html
AFAIK,nginx 不支持 X-SendFile。Nginx 有自己的扩展,称为 X-Accel-Redirect。
您将在此处找到有关此内容的更多信息: https ://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
在 github 上还有一个 rails 插件实现了这个功能:goncalossilva/X-Accel-Redirect
使文件在不可预知的 URL上可用是目前在某些生产系统中使用的简单解决方案。
例如:GitLab。下图上传到了一个私有仓库的 issue,https://gitlab.com/cirosantilli/test-private/issues/1,但是你仍然可以看到它:
请注意90574279de
自动添加到 URL 的不可猜测的前缀。
Bitbucket(非 Rails)也使用这种技术。
如果您想将内容交付与您的 Rails 身份验证和授权系统联系起来,那么您基本上必须将内容放在控制器后面。
如果您正在寻找一种更简单的登录方法,您可以使用 HTTP Auth 和托管环境中的设置来处理它(例如,使用 htaccess)。