2010-05-02 14 views
5

He aquí una historia:Cómo almacenar imágenes y vídeos privados en Ruby on Rails

  • Un usuario debe ser capaz de subir una imagen.
  • El usuario A debe poder establecer una privacidad. ("Público" o "Privado").
  • usuario B no debería ser capaz de acceder a las imágenes "privado" de usuario A.

Estoy planeando usuario Paperclip para hacer frente a las subidas.

Si almaceno las imágenes en "RAILS_ROOT/public/images", cualquiera que pueda adivinar el nombre de los archivos puede acceder a los archivos. (por ejemplo, accediendo al http://example.com/public/images/uploads/john/family.png)

Necesito mostrar las imágenes usando etiquetas img, por lo que no puedo colocar un archivo excepto public.

¿Cómo puedo asegurarme de que otras personas no puedan acceder a las imágenes de un usuario o grupo?

(Si no puedo lograr esto con el Paperclip, lo que es una buena solución?)

Respuesta

4

Tendría Paperclip usar S3 en el back-end, los archivos cargados configurados como privados, y luego usar "cadena de consulta de solicitud de autenticación alternativo" a generar las URL para mis etiquetas de imagen.

http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

+0

Esta es una idea muy, muy buena, especialmente con CloudFront. – Zack

+0

Sí, funciona genial. Callmeed publicó lo mismo que yo al mismo tiempo, pero también muestra algunos códigos. Echa un vistazo a lo que publicó y dale una seria consideración. – jdl

8

Usted puede hacer que su salida del servidor carriles de los contenidos de los archivos de imagen. Esto se hace a través de una acción de controlador (la mayoría de las acciones imprimen HTML, pero esta imprimirá JPG, por ejemplo).

Luego puede usar su sistema de autorización para restringir el acceso en el nivel de controlador!

class ImagesController 
    #Default show Image method streams the file contents. 
    #File doesn't have to be in public/ dir 
    def show 
    send_file @image.filename, :type => @image.content_type, 
       :disposition => 'inline' 
    end 

    # Use your favorite authorization system to restrict access 
    filter_access_to :show, :require => :view, :attribute_check => :true 
end 

En el código HTML que puede usar:

<img src="/images/show/5" /> 
+0

Gracias. Esto es interesante. Voy a ver esto. –

+2

En este caso, es razonable dejar que el servidor web sirva los archivos enviados por 'send_file'. Eche un vistazo a 'X-Accel-Redirect' en Nginx o' X-Sendfile' en Apache. Enlaces útiles: [1] (http://maxresponsemedia.com/rails/nginx-x-accel-redirect-setup-in-rails-3/), [2] (http://thedataasasylum.com/articles/how -rails-nginx-x-accel-redirect-work-together.html), [3] (http://airbladesoftware.com/notes/rails-nginx-x-accel-mapping), [4] (http://www.therailsway.com/2009/2/22/file-downloads-done-right/). – mrzasa

4

Así es como hice esto en una aplicación similar.

  • Almacene sus imágenes en Amazon S3 en lugar del sistema de archivos local. Paperclip lo admite.
  • Establezca su: s3_permissions en "privado" en las opciones de Sujetapapeles
  • En su modelo de Imagen, defina un método que le permita generar una url autorizada y limitada en el tiempo para la imagen.

mina se parece a esto:

def s3_url(style = :original, time_limit = 30.minutes) 
    self.attachment.s3.interface.get_link(attachment.s3_bucket.to_s, attachment.path(style), time_limit) 
end 
  • A continuación, puede mostrar imágenes a las personas sólo si están autorizados para verlos (práctica que como usted quiera) -y no tiene que preocuparse personas adivinando/viendo imágenes privadas. También evita que pasen las URL desde que caducan (la URL tiene un token).
  • Tenga en cuenta que lleva su aplicación generar las URL autorizadas para cada imagen. Entonces, si tiene varias imágenes en una página, esto afectará el tiempo de carga.
+0

¿Tiene alguna sugerencia para optimizar este enfoque para aplicaciones pesadas de lectura de imágenes? Parece que voy a tener muchos éxitos adicionales de aplicaciones ... – Jared

1

Si desea alojar archivos usted mismo, puede realizar la autenticación en el nivel del controlador como se ha sugerido. Una de mis aplicaciones tiene un AssetController que maneja la entrega de archivos desde el directorio 'privado', por ejemplo.

Una cosa que quería agregar es que debe revisar this guide para configurar X-Sendfile, que le permitirá a su aplicación decirle al servidor web que se encargue de enviar los archivos. Verás un rendimiento mucho mejor con este enfoque.