2010-01-26 21 views
16

Utrzymuję aplikację Rails, która ma zawartość w folderze publicznym/folderze, który będzie teraz musiał być chroniony przez login. Rozważamy przeniesienie tych folderów plików do ścieżki poza publicznym/i zapisanie kontrolera Railsów, aby obsłużyć zawartość.Ochrona zawartości publicznej/w aplikacji Railsowej

Zanim zaczniemy to pisać, byłem ciekawy, czy ktoś inny wpadł na ten problem? Szukałem klejnotów/wtyczek, które mogły już to zrobić, ale niczego nie znalazłem. Czy ktoś stworzył dla tego klejnot?

Odpowiedz

0

Jeśli chcesz związać zawartości przesyłki z uwierzytelniania i autoryzacji systemu Rails, to w zasadzie trzeba umieścić treść za pomocą kontrolera.

Jeśli szukasz prostszego sposobu logowania, możesz obsłużyć go za pomocą protokołu HTTP Auth i ustawień w swoim środowisku hostingowym (na przykład przy użyciu htaccess).

16

Zrobiłem to na stronie, gdzie ludzie płacą za pobieranie pewnych plików, a pliki są przechowywane w RAILS_ROOT/private. Pierwszą rzeczą, którą musisz wiedzieć, jest to, że chcesz, aby serwer WWW obsługiwał wysyłanie pliku, w przeciwnym razie Twoja aplikacja zostanie wstrzymana, przesyłając duże pliki, a to szybko zatrzyma twoją witrynę, jeśli masz jakiś plik do pobrania. Tak więc, jeśli chcesz sprawdzić autoryzację w kontrolerze, potrzebujesz również sposobu na przejęcie kontroli nad pobieraniem z powrotem na serwer WWW. Najlepszym sposobem na zrobienie tego (o czym wiem) jest nagłówek X-Sendfile obsługiwany przez Nginx, Apache (z modułem) i inne. Po skonfigurowaniu X-Sendfile, gdy twój serwer internetowy otrzyma z aplikacji nagłówek , przejmuje wysyłanie pliku do klienta.

Gdy masz X-Sendfile pracuje na serwerze WWW, prywatny sposób kontroler jak to jest pomocne:

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

Wtedy twoje działania kontroler mógłby wyglądać następująco:

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

Oczywiście Twoja metoda autoryzacji będzie się różnić i będziesz musiał zmienić nagłówki, jeśli oferujesz pliki inne niż pliki PDF lub chcesz, aby plik był wyświetlany w przeglądarce (pozbądź się typu zawartości application/force-download).

+5

Dlaczego nie używa się wbudowanej metody send_file? –

+3

Ponieważ nie wiedziałem o tym! Każdy, kto użyje tej techniki, powinien usunąć moją kaleką definicję metody "send_file", a zamiast tego wywołać Railsowy plik 'send_file path,: type =>" application/pdf ",: x_sendfile => true'. Dzięki za wiadomość, Ryan. –

+0

Skomentowałem dalej "X-Sendfile" pod adresem: http://stackoverflow.com/a/26884350/895245 –

0

Making plik dostępny w nieprzewidywalny URL jest prosty rozwiązanie obecnie stosowane w niektórych systemach produkcyjnych.

Np .: GitLab.Poniższy obraz został przesłany do emisji prywatnej repozytorium, https://gitlab.com/cirosantilli/test-private/issues/1, ale wciąż można go zobaczyć:

Zanotować unguessable 90574279de prefiks automatycznie dodawany do adresu URL.

Bitbucket (nie-szyny) również używa tej techniki.

Powiązane problemy