2010-05-02 5 views
5

Ecco una storia:Come conservare foto private e video in Ruby on Rails

  • utente A deve essere in grado di caricare un'immagine.
  • L'utente A dovrebbe essere in grado di impostare una privacy. ("Pubblico" o "Privato").
  • utente B non dovrebbe essere in grado di accedere alle immagini "Private" di utente A.

Sto pensando di utente Paperclip per trattare con i caricamenti.

Se memorizzo le immagini in "RAILS_ROOT/public/images", chiunque possa indovinare il nome dei file potrebbe accedere ai file. (ad esempio, accesso a http://example.com/public/images/uploads/john/family.png)

Ho bisogno di mostrare le immagini usando i tag img, quindi non posso inserire un file tranne public.

Come posso garantire che le immagini di un utente o gruppo non siano accessibili da altri?

(Se non posso raggiungere questo obiettivo con Paperclip, ciò che è una buona soluzione?)

risposta

4

avrei Paperclip utilizzare S3 sul back-end, i file caricati impostati a privati, e quindi utilizzare "Query String richiesta di autenticazione alternativo" a generare gli URL per i miei tag immagine.

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

+0

Questa è un'idea molto, molto buona, specialmente con CloudFront. – Zack

+0

Sì, funziona benissimo. Callmeed ha pubblicato la stessa cosa di me allo stesso tempo, ma mostra anche del codice. Dai un'occhiata a ciò che ha pubblicato e prendilo in seria considerazione. – jdl

8

si potrebbe rendere il server di uscita binari il contenuto dei file di immagine. Ciò avviene tramite un'azione del controller (la maggior parte delle azioni stampano HTML, ma questo stamperà JPG, ad esempio).

Quindi è possibile utilizzare il proprio sistema di autorizzazione per limitare l'accesso a livello di controller!

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 

Nel codice HTML è possibile utilizzare:

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

Grazie. Questo è interessante. Vedrò questo. –

+2

In questo caso è ragionevole lasciare che il server web serva i file inviati da 'send_file'. Dai un'occhiata a 'X-Accel-Redirect' in Nginx o' X-Sendfile' in Apache. Link utili: [1] (http://maxresponsemedia.com/rails/nginx-x-accel-redirect-setup-in-rails-3/), [2] (http://thedataasylum.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

Ecco come ho fatto questo in un'applicazione simile.

  • Memorizza le immagini su Amazon S3 anziché sul file system locale. Paperclip supporta questo.
  • Imposta il tuo: s3_permissions su "privato" nelle tue opzioni Paperclip
  • Nel tuo modello Immagine, definisci un metodo che ti consente di generare un URL autorizzato limitato nel tempo per l'immagine.

miniera di simile a questa:

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 
  • È quindi possibile mostrare le immagini alle persone solo se sono autorizzati a vederli (implementare che più vi piace) -e non deve preoccuparsi persone che indovinano/guardano immagini private. Inoltre impedisce loro di passare URL in giro da quando scadono (l'URL ha un token in esso).
  • Tieni presente che per la tua app è necessario tempo per generare gli URL autorizzati per ogni immagine. Quindi, se hai diverse immagini su una pagina, questo influirà sul tempo di caricamento.
+0

Avete suggerimenti sull'ottimizzazione di questo approccio per le applicazioni pesanti leggere con immagini? Sembra che avrò molti successi in più per le app ... – Jared

1

Se si desidera ospitare file autonomamente, è possibile eseguire l'autenticazione a livello di controller come suggerito. Una delle mie applicazioni ha un AssetController che gestisce la pubblicazione di file dalla directory "privata", ad esempio.

Una cosa che volevo aggiungere è che è necessario rivedere this guide per l'impostazione di X-Sendfile, che consentirà all'applicazione di comunicare al server Web di gestire effettivamente l'invio dei file. Vedrai prestazioni molto migliori con questo approccio.