2010-01-26 10 views
16

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

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

Respuesta

0

Si quiere amarrar la entrega de contenido con su autenticación de rieles y del sistema de autorización, entonces usted tiene esencialmente para poner el contenido detrás de un controlador.

Si está buscando un enfoque de inicio de sesión más simple, puede manejarlo con HTTP Auth y configuraciones en su entorno de alojamiento (usando htaccess, por ejemplo).

16

He hecho esto en un sitio donde la gente paga para descargar ciertos archivos, y los archivos están almacenados en RAILS_ROOT/private. Lo primero que debe saber es que desea que el servidor web se encargue del envío del archivo; de lo contrario, su aplicación se retrasará al transmitir archivos de gran tamaño, lo que hará que su sitio se detenga rápidamente si tiene algún tipo de volumen de descarga. Entonces, 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 hacerlo (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 desde su aplicación, se hace cargo de enviar el archivo al cliente.

Una vez que tenga X-Sendfile de trabajo para su servidor web, un método de control privado de este tipo 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 

A continuación, el controlador de la acción podría ser algo como esto:

## 
# 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 visualice en el navegador (elimine el tipo de contenido application/force-download).

+5

¿Por qué no está utilizando el método integrado send_file? –

+3

¡Porque no lo sabía! Cualquiera que use esta técnica debería eliminar mi definición de método 'send_file' paralizado y, en su lugar, invocar la ruta' send_file' incluida en Rails,: type => "application/pdf",: x_sendfile => true'. Gracias por la nota, Ryan. –

+0

He comentado más sobre 'X-Sendfile' en: http://stackoverflow.com/a/26884350/895245 –

0

Hacer el archivo disponible en una URL impredecible es un simple solución actualmente utilizada en algunos sistemas de producción.

Por ej .: GitLab.La siguiente imagen fue subida a un problema de un depósito privado, https://gitlab.com/cirosantilli/test-private/issues/1, pero todavía se puede ver que:

Nota del inimaginable 90574279de prefijo añade automáticamente a la URL.

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

Cuestiones relacionadas