2010-01-26 11 views
16

Gestisco un'applicazione Rails con contenuto nella cartella pubblica/che ora deve essere protetta da un accesso. Stiamo considerando di spostare tali cartelle di file in un percorso esterno al pubblico/e di scrivere un controller Rails per rendere disponibile il contenuto.Protezione del contenuto del pubblico/in un'applicazione Rails

Prima di iniziare a scrivere questo, ero curioso di sapere se qualcun altro si è imbattuto in questo tipo di problema? Ho cercato alcune gemme/plugin che potrebbero già farlo ma non hanno trovato nulla. Qualcuno ha creato un gioiello per questo?

risposta

0

Se si vuole legare la distribuzione di contenuti con l'autenticazione Rails e sistema di autorizzazione, allora si hanno essenzialmente a mettere il contenuto dietro un controller.

Se si sta osservando un approccio di accesso più semplice, è possibile gestirlo con HTTP Auth e le impostazioni nel proprio ambiente di hosting (utilizzando htaccess, ad esempio).

16

L'ho fatto su un sito dove le persone pagano per scaricare determinati file e i file sono archiviati in RAILS_ROOT/private. La prima cosa da sapere è che vuoi che il server web gestisca l'invio del file, altrimenti la tua app verrà trattenuta trasmettendo file di grandi dimensioni e questo porterà rapidamente il tuo sito a fermarsi se hai qualsiasi tipo di volume di download. Pertanto, se è necessario verificare l'autorizzazione in un controller, è necessario anche un modo per trasferire il controllo del download al server Web. Il modo migliore per farlo (che io sappia) è l'intestazione X-Sendfile, che è supportata da Nginx, Apache (con modulo) e altri. Con X-Sendfile configurato, quando il tuo server web riceve un'intestazione dalla tua app, riprende l'invio del file al client.

Una volta che avete X-Sendfile lavorare per il proprio server web, un metodo di controllo privato come questo è utile:

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

Allora la vostra azione di controllo potrebbe essere simile a questa:

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

Ovviamente il tuo metodo di autorizzazione varierà e dovrai modificare le intestazioni se offri file diversi dai PDF o desideri che il file venga visualizzato nel browser (elimina il tipo di contenuto application/force-download).

+5

Perché non si utilizza il metodo send_file incorporato? –

+3

Perché non lo sapevo! Chiunque usi questa tecnica dovrebbe rimuovere la mia definizione di metodo 'send_file' criptata e invece chiamare il percorso send_file di Rails-incluso,: type =>" application/pdf ",: x_sendfile => true'. Grazie per il biglietto, Ryan. –

+0

Ho commentato ulteriormente su 'X-Sendfile' a: http://stackoverflow.com/a/26884350/895245 –

0

Rendere il file disponibile a un URL imprevedibile è un semplice soluzione attualmente utilizzata in alcuni sistemi di produzione.

E.g .: GitLab.L'immagine seguente è stato caricato a un problema di un repository privato, https://gitlab.com/cirosantilli/test-private/issues/1, ma si può ancora vedere:

Annotare il unguessable 90574279de prefisso aggiunto automaticamente al URL.

Anche Bitbucket (non-Rails) utilizza questa tecnica.

Problemi correlati