Защита содержимого public/ в приложении Rails

Я поддерживаю приложение Rails с содержимым в папке public/, которое теперь нужно будет защитить с помощью входа в систему. Мы рассматриваем возможность перемещения этих папок с файлами по пути за пределами public/ и написания контроллера Rails для обслуживания содержимого.

Прежде чем мы начнем писать это, мне было любопытно, сталкивался ли кто-нибудь еще с такой проблемой? Я искал некоторые драгоценные камни/плагины, которые могли бы уже делать это, но ничего не нашел. Кто-нибудь создал драгоценный камень для этого?


person Matt Hawkins    schedule 26.01.2010    source источник


Ответы (5)


Я сделал это на сайте, где люди платят за загрузку определенных файлов, и эти файлы хранятся в RAILS_ROOT/private. Первое, что нужно знать, это то, что вы хотите, чтобы веб-сервер обрабатывал отправку файла, иначе ваше приложение будет задержано при передаче больших файлов, и это быстро остановит ваш сайт, если у вас есть какой-либо объем загрузки. Итак, если вам нужно проверить авторизацию в контроллере, то вам также нужен способ передать управление загрузкой обратно на веб-сервер. Лучший способ сделать это (известный мне) — использовать заголовок X-Sendfile, который поддерживается Nginx, Apache (с модулем) и другими. С настроенным X-Sendfile, когда ваш веб-сервер получает заголовок X-Sendfile от вашего приложения, он берет на себя отправку файла клиенту.

Если у вас есть X-Sendfile, работающий на вашем веб-сервере, вам может помочь такой метод частного контроллера:

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

Тогда действие вашего контроллера может выглядеть примерно так:

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

Очевидно, что ваш метод авторизации будет другим, и вам нужно будет изменить заголовки, если вы предлагаете файлы, отличные от PDF, или вы хотите, чтобы файл просматривался в браузере (избавьтесь от типа контента application/force-download).

person Alex Reisner    schedule 26.01.2010
comment
Почему не используется встроенный метод send_file? - person Ryan Bigg; 10.05.2010
comment
Потому что я не знал об этом! Любой, кто использует эту технику, должен удалить мое кривое определение метода send_file и вместо этого вызвать включенный в Rails метод send_file path, :type => "application/pdf", :x_sendfile => true. Спасибо за заметку, Райан. - person Alex Reisner; 10.05.2010
comment
Я прокомментировал X-Sendfile по адресу: stackoverflow.com/a/26884350/895245. - person Ciro Santilli 新疆再教育营六四事件ۍ 12.11.2014

Вы можете использовать Amazon S3. Вы можете использовать контроллеры для создания и обслуживания URL-адресов за вашей безопасной зоной, а также у них есть функция, которая в основном делает ресурсы доступными только в течение определенного периода времени после создания URL-адреса.

Проверьте этот URL: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

person Doug R    schedule 26.01.2010

Насколько я знаю, X-SendFile не поддерживается nginx. У Nginx есть собственное расширение, позволяющее это сделать, которое называется X-Accel-Redirect.

Дополнительную информацию об этом можно найти здесь: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/

На github также есть подключаемый модуль rails, реализующий эту функцию: goncalossilva/X-Accel-Redirect

person Elthariel    schedule 06.07.2010

Если вы хотите связать доставку контента с вашей системой аутентификации и авторизации Rails, вам, по сути, нужно поместить контент за контроллер.

Если вы ищете более простой подход к входу в систему, вы можете справиться с ним с HTTP-аутентификацией и настройками в вашей среде хостинга (например, с помощью htaccess).

person Toby Hede    schedule 26.01.2010

Предоставление доступа к файлу по непредсказуемому URL-адресу — это простое решение, которое в настоящее время используется в некоторых производственных системах.

Например: Гитлаб. Следующее изображение было загружено в задачу частного репозитория, https://gitlab.com/cirosantilli/test-private/issues/1, но вы все равно можете его увидеть:

Обратите внимание на неугадываемый префикс 90574279de, который автоматически добавляется к URL-адресу.

Bitbucket (не Rails) также использует эту технику.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 22.11.2014