ruby-on-rails - guide - ruby on rails tutorial



Proteger el contenido del público/en una aplicación Rails (4)

AFAIK, X-SendFile no es compatible con nginx. Nginx tiene su propia extensión que permite esto, llamada X-Accel-Redirect.

Encontrará más información sobre esto aquí: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/

También hay un complemento de rieles implementando esta característica, en github: goncalossilva/X-Accel-Redirect

https://src-bin.com

Estoy manteniendo una aplicación de Rails que tiene contenido en la carpeta pública / que ahora deberá estar protegida por un inicio de sesión. Estamos considerando mover esas carpetas de archivos a una ruta fuera del público y escribir un controlador Rails para entregar el contenido.

Antes de comenzar a escribir esto, tenía curiosidad si alguien más se había encontrado con este tipo de problema. Busqué algunas gemas / complementos que ya podrían hacer esto, pero no encontré nada. ¿Alguien ha creado una gema para esto?



Answer #2

Hacer que el archivo esté disponible en una URL impredecible es una solución simple que se usa actualmente en algunos sistemas de producción.

Por ejemplo: GitLab. La siguiente imagen se cargó en un problema de un repositorio privado, https://gitlab.com/cirosantilli/test-private/issues/1 , pero aún puede verlo:

Tenga en cuenta que el prefijo 90574279de se puede agregar automáticamente a la URL.

Bitbucket (non-Rails) también utiliza esta técnica.


Answer #3

He hecho esto en un sitio donde la gente paga para descargar ciertos archivos, y los archivos se almacenan en RAILS_ROOT/private . Lo primero que debe saber es que desea que el servidor web maneje el envío del archivo; de lo contrario, su aplicación se retrasará al transmitir archivos grandes y esto detendrá su sitio rápidamente si tiene algún tipo de volumen de descarga. Por lo tanto, si necesita verificar la autorización en un controlador, también necesita una forma de pasar el control de la descarga al servidor web. La mejor manera de hacer esto (que yo sepa) es el encabezado X-Sendfile, que es compatible con Nginx, Apache (con módulo) y otros. Con X-Sendfile configurado, cuando su servidor web recibe un encabezado X-Sendfile desde su aplicación, se encarga de enviar el archivo al cliente.

Una vez que tenga X-Sendfile trabajando para su servidor web, un método de controlador privado como este es útil:

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

Entonces, la acción de tu controlador podría verse así:

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

Obviamente, su método de autorización variará y deberá cambiar los encabezados si está ofreciendo archivos que no sean archivos PDF o si desea que el archivo se vea en el navegador (elimine el tipo de contenido de la application/force-download ).





public