Как хранить данные на S3 и безопасный доступ пользователей к клиенту API/iOS с rails?

Я новичок в написании Rails и API. Мне нужна помощь в решении S3. Вот моя проблема.

Я пишу API для приложения iOS, где пользователи вступают в систему с API Facebook на iOS. Сервер проверяет пользователя на проблемы с токеном Facebook для пользователя iOS и выдает временный токен сеанса. С этого момента пользователю необходимо загрузить контент, который хранится в S3. Этот контент принадлежит только пользователю и подмножеству его друзей. Этот пользователь может добавить больше контента на S3, к которому можно получить доступ той же группой людей. Я думаю, это похоже на прикрепление файла к группе Facebook...

Существует два способа взаимодействия пользователя с S3: оставить его на сервере или заставить сервер выпустить временный токен S3 (не уверены в возможностях здесь), и пользователь может напрямую набирать URL-адреса контента к S3. Я нашел этот вопрос, говорящий о подходах, однако он действительно устарел (2 года назад): Архитектурный вопрос и вопрос о загрузке фотографий с iPhone-приложения и S3

Итак, вопросы:

  • Есть ли способ ограничить доступ пользователей к некоторому контенту на S3 при выдаче временного токена? Как я могу это сделать? Предположим, что есть... скажем, 100 000 или более пользователей.
  • Можно ли позволить устройству iOS напрямую вытащить этот контент?
  • Или должен ли сервер контролировать весь контент, проходящий (это, конечно, решает проблему)? Означает ли это, что мне нужно загрузить весь контент на сервер, прежде чем передавать его подключенным пользователям?
  • Если вы знаете рельсы... могу ли я использовать paperclip и aws-sdk gems для достижения этой настройки?

Извините за несколько вопросов, и я ценю любое понимание проблемы. Спасибо:)

Ответ 1

Используя aws-sdk gem, вы можете получить временный подписанный URL-адрес для любого объекта S3, вызвав url_for:

s3 = AWS::S3.new(
  :access_key_id => 1234,
  :secret_access_key => abcd
)
object = s3.buckets['bucket'].objects['path/to/object']
object.url_for(:get, { :expires => 20.minutes.from_now, :secure => true }).to_s

Это даст вам подписанный, временный URL-адрес использования только для этого объекта в S3. Он истекает через 20 минут (в этом примере), и это полезно только для одного объекта.

Если у вас много объектов, которые нужны клиенту, вам нужно будет выпустить много подписанных URL-адресов.

Или должен позволить серверу управлять всем контентом (это, конечно, решает безопасность)? Означает ли это, что мне нужно загрузить весь контент на сервер, прежде чем передавать его подключенным пользователям?

Обратите внимание, что это не означает, что серверу необходимо загрузить каждый объект, ему нужно только аутентифицировать и авторизировать определенные клиенты для доступа к определенным объектам в S3.

API-документы от Amazon: http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

Ответ 2

В приведенных выше ответах используется старый жемчуг aws-sdk-v1, а не новый aws-sdk-resources версии 2.

Новый способ:

aws_resource = Aws::S3::Resource::new
aws_resource.bucket('your_bucket').object('your_object_key').presigned_url(:get, expires_in: 1*20.minutes)

где your_object_key - это путь к вашему файлу. Если вам нужно посмотреть это, вы должны использовать что-то вроде:

s3 = Aws::S3::Client::new
keys = []
s3.list_objects(bucket: 'your_bucket', prefix: 'your_path').contents.each { |e| 
  keys << e.key
}

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

Ссылка

http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method