Rails: запутывает URL-адреса изображений на Amazon S3? (проблема безопасности) - PullRequest
2 голосов
/ 12 февраля 2010

Короче говоря, достаточно сказать, что мое приложение на Rails позволяет пользователям загружать в приложение изображения, которые они хотят сохранить в приложении (то есть, без хотлинкинга).

Поэтому я пытаюсь найти способ запутать URL-адреса изображений, чтобы адрес изображения зависел от того, вошел ли пользователь на сайт или нет, поэтому, если кто-то попытался создать ссылку наimage, они получили бы ошибку 401 отказано в доступе.

Я думал, что если бы я мог направить запрос через контроллер, я мог бы повторно использовать большую часть авторизации, которую я уже встроил в свое приложение,но я застрял там.

Мне бы хотелось, чтобы мои изображения были доступны через URL-адрес одного из моих контроллеров, например:

http://railsapp.com/images/obfuscated?member_id=1234&pic_id=7890

Если пользователь гдещелкните правой кнопкой мыши на изображении, отображаемом на веб-сайте, и выберите «Скопировать адрес», а затем вставьте его, это будет ОДИН И ТОТ ЖЕ URL-адрес (как, например, не будет выдавать, где изображение фактически размещено).Фактическое изображение будет жить по URL-адресу, например так:

http://s3.amazonaws.com/s3username/assets/member_id/pic_id.extension

Возможно ли это сделать?Возможно, используя метод Rails * render?Или что-то другое?Я знаю, что PHP может возвращать правильные заголовки, чтобы браузер думал, что это изображение, но я не знаю, как это сделать в Rails ...

ОБНОВЛЕНИЕ: я хочу, чтобы все пользователи приложениячтобы иметь возможность просматривать изображения, если и только если они в настоящее время вошли на сайт.Если у пользователя нет активного сеанса на сайте, прямой доступ к изображениям должен привести к появлению общего изображения или сообщения об ошибке.

Ответы [ 5 ]

2 голосов
/ 02 января 2011

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

Другим преимуществом этого является доступность файлов и будущая масштабируемость системы.

2 голосов
/ 12 февраля 2010

S3 позволяет создавать строки запросов для запросов, которые позволяют ограниченное по времени скачивание частного объекта. Вы можете сгенерировать URL для изображения уникально для каждого пользователя с коротким тайм-аутом для предотвращения повторного использования.

См. документацию , ищите раздел "Альтернатива аутентификации запроса строки запроса". Я бы связался напрямую, но javascript, нарушающий фрейм, предотвращает это.

1 голос
/ 12 февраля 2010

Спасибо за ваши ответы, но я все еще скептически отношусь к тому, является ли "тайм-аут" URL-адреса от Amazon очень эффективным способом.

Я обновил свой вопрос выше, чтобы немного яснее понять, что я пытаюсь сделать и пытаюсь предотвратить.

После некоторых экспериментов я нашел способ сделать то, что я хочу сделать в своем приложении Rails, хотя это решение не лишено недостатков. По сути, я создал image_tag с URL-адресом, указывающим на контроллер и принимающим параметр path. Этот контроллер сначала проверяет, авторизован ли пользователь для просмотра изображения, затем извлекает содержимое изображения в отдельном запросе и сохраняет содержимое в переменной экземпляра, который затем передается в представление repond_to для возврата изображения, успешно запутывая фактический URL-адрес изображения (поскольку этот запрос выполняется отдельно).

Минусы:

  1. Добавляет к запросу время (мне кажется, что дополнительное время, необходимое для выполнения этого двойного запроса, приемлемо, учитывая конфиденциальность, которую дает мне этот метод)
  2. Добавляет беспорядок в представления и маршруты (небольшое количество, может быть, немного больше, чем хотелось бы)
  3. Если пользователь авторизован и пытается получить доступ к изображению напрямую, изображение загружается немедленно, а не отображается в браузере (кто-нибудь знает, как это исправить? Изменить заголовки HTTP? Похоже, это происходит только с jpg хотя ...)
  4. Вы должны сделать отдельное представление для каждого формата файла, который вы намереваетесь обслуживать (два для меня, jpg и png)

Есть ли какие-либо другие минусы или соображения, которые я должен знать об этом методе? Пока что я перечислил, я могу жить с ...

(Рефакторинг приветствуется.)


application_controller.rb

class ApplicationController < ActionController::Base

  def obfuscate_image
    respond_to do |format|
      if current_user
        format.jpg { @obfuscated_image = fetch_url "http://s3.amazonaws.com/#{Settings.bucket}/#{params[:path]}" }
      else
        format.png { @obfuscated_image = fetch_url "#{root_url}/images/assets/profile/placeholder.png" }
      end
    end
  end

  protected

  # helps us fetch an image, obfuscated
  def fetch_url(url)
    r = Net::HTTP.get_response(URI.parse(url))
    if r.is_a? Net::HTTPSuccess
      r.body
    else
      nil
    end
  end
end

views / application / obfuscate_image.png.haml & views / application / obfuscate_image.jpg.haml

= @obfuscated_image

routes.rb

map.obfuscate_image 'obfuscate_image', :controller => 'application', :action => 'obfuscate_image'

конфиг / environment.rb

Mime::Type.register "image/png", :png
Mime::Type.register "image/jpg", :jpg

Вызов запутанного изображения

= image_tag "/obfuscate_image?path=#{@user.profile_pic.path}"
1 голос
/ 12 февраля 2010

Должны ли изображения быть доступны только этому пользователю или вы хотите сделать его доступным для группы пользователей (друзей)?

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

Если первое, вы можете сохранить изображение на сервере как MD5 (image_file_name_as_exposed_to_user + logged_in_username_from_cookie). Когда пользователь запрашивает image_file_name_as_exposed_to_user, в вашем приложении rails создайте имя файла изображения, как упомянуто ранее, а затем откройте файл в приложении rails и запишите его (после соответствующей установки Content-Type в заголовке ответа соответственно). Это безопасно по замыслу.

Если изображение может быть передано друзьям, вам не следует включать имя пользователя в созданное имя файла, но остальные советы должны работать.

0 голосов
/ 12 февраля 2010

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

Между прочим, сигналы 37 не считают это большой проблемой, потому что, если я просматриваю изображение в своей личной учетной записи Backpack, я вижу общедоступный URL-адрес S3 в адресной строке браузера. Ваш пробег может варьироваться ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...