Я новичок в написании Rails и API. Мне нужна помощь с решением для хранения S3. Вот моя проблема.
Я пишу API для приложения iOS, где пользователи входят в систему с помощью API Facebook на iOS. Сервер проверяет пользователя по токену, который Facebook выдает пользователю iOS, и выдает временный токен сеанса. С этого момента пользователю необходимо загрузить контент, который хранится в S3. Этот контент принадлежит только пользователю и некоторой части его друзей. Этот пользователь может добавлять в S3 больше контента, доступ к которому может получить одна и та же группа людей. Я думаю, это похоже на прикрепление файла к группе Facebook ...
Есть два способа взаимодействия пользователя с S3 ... оставьте это на сервере или попросите сервер выдать временный токен S3 (не уверен в возможностях здесь), и пользователь может перейти по URL-адресам контента непосредственно к S3. Я обнаружил, что этот вопрос касается подходов, однако он действительно устарел (2 года назад): архитектурный и дизайнерский вопрос о загрузке фотографий из приложения для iPhone и S3.
Итак, вопросы:
- Есть ли способ ограничить доступ пользователя только к некоторому контенту на S3 при выдаче временного токена? Как я могу это сделать? Предположим, есть ... скажем, 100 000 или более пользователей.
- Разрешить устройству iOS извлекать этот контент напрямую?
- Или следует позволить серверу контролировать передачу всего контента (это, конечно, решает проблему безопасности)? Означает ли это, что я должен загрузить весь контент на сервер, прежде чем передать его подключенным пользователям?
- Если вы знаете рельсы ... могу ли я использовать скрепку и драгоценные камни aws-sdk для достижения такой настройки?
Приносим извинения за несколько вопросов, и я ценю любое понимание проблемы. Благодарность :)
Ответы:
Используя гем aws-sdk , вы можете получить временный подписанный 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: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
источник
ACCESS_KEY_ID
(не помню, с макушки), но это не должно быть секретом.AWS_ACCESS_KEY_ID
. Сначала я думал, чтоAWS_SECRET_ACCESS_KEY
это тоже отображается, но это не так.В приведенных выше ответах используется старый гем aws-sdk-v1, а не новая версия 2 aws-sdk-resources.
Новый способ:
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
источник
expires_in
ожидает данные в виде секунд, просто убедитесь, что вы преобразовали их в первую очередь.