Jak przechowywać dane w S3 i umożliwić dostęp użytkownikom w bezpieczny sposób za pomocą klienta rails API / iOS?

Jestem nowy w pisaniu Rails i API. Potrzebuję pomocy w rozwiązaniu S3 storage. Oto mój problem.

Piszę API dla aplikacji na iOS, gdzie użytkownicy logują się za pomocą API Facebook na iOS. Serwer weryfikuje użytkownika względem tokenu, który Facebook wydaje użytkownikowi iOS i wydaje tymczasowy token sesji. Od tego momentu użytkownik musi pobrać zawartość przechowywaną w S3. Ta zawartość należy tylko do użytkownika i podzbioru jego znajomych. Ten użytkownik może dodać więcej treści do S3, do którego dostęp mają te same osoby. Myślę, że jest to podobne do dołączania pliku do grupy Facebook...

Istnieją 2 sposoby interakcji użytkownika z S3... zostaw to serwerowi lub poproś serwer o wystawienie tymczasowego tokena S3 (Nie jestem pewien możliwości tutaj), a użytkownik może trafić na adresy URL zawartości bezpośrednio do S3. Znalazłem to pytanie mówiące o podejściach, jednak jest to naprawdę datowane (2 lata temu): pytanie architektoniczne i projektowe o przesyłanie zdjęcia z aplikacji iPhone i S3

Więc pytania:

  • Czy istnieje sposób, aby ograniczyć dostęp Użytkownika do tylko niektórych treści na S3, gdy tymczasowy token jest wydawany? Jak mogę to zrobić? Załóżmy, że jest... powiedzmy 100 000 lub więcej użytkowników.
  • czy to dobry pomysł, aby pozwolić urządzeniu iOS wyciągnąć tę zawartość bezpośrednio?
  • czy serwer powinien kontrolować przesyłanie całej zawartości (to oczywiście rozwiązuje kwestie bezpieczeństwa)? Czy to oznacza, że muszę pobrać całą zawartość na serwer przed przekazanie go podłączonym użytkownikom?
  • Jeśli znasz rails... czy mogę użyć paperclip i aws-sdk gems, aby osiągnąć taką konfigurację?

Przepraszam za wiele pytań i doceniam każdy wgląd w problem. Dzięki:)

Author: Community, 2012-05-30

2 answers

Używając gem aws-sdk , możesz uzyskać tymczasowy podpisany adres url dla dowolnego obiektu S3, wywołując 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

To da ci podpisany, tymczasowy URL użycia tylko dla tego obiektu W S3. Wygasa po 20 minutach (w tym przykładzie) i jest dobry tylko dla tego jednego obiektu.

Jeśli masz wiele obiektów, których potrzebuje klient, musisz wydać wiele podpisanych adresów URL.

Lub powinien pozwolić serwerowi kontrolować wszystkie przekazywane treści (rozwiązuje to bezpieczeństwo oczywiście)? Czy to oznacza, że muszę pobrać całą zawartość na serwer przed przekazaniem jej połączonym użytkownikom?

Zauważ, że nie oznacza to, że serwer musi pobierać każdy obiekt, tylko musi uwierzytelnić i autoryzować określonych klientów, aby uzyskać dostęp do określonych obiektów w S3.

API docs od Amazon: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

 112
Author: ejdyksen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-19 16:11:12

Powyższe odpowiedzi używają starego klejnotu aws-sdk-v1 zamiast nowego aws-sdk-resources w wersji 2.

Nowa droga to:

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

Gdzie your_object_key jest ścieżką do pliku. Jeśli chcesz to sprawdzić, użyj czegoś w stylu:

s3 = Aws::S3::Client::new
keys = []
s3.list_objects(bucket: 'your_bucket', prefix: 'your_path').contents.each { |e| 
  keys << e.key
}
Ta informacja była zaskakująco trudna do odkopania, a ja prawie się poddałem i wykorzystałem starsze gem.

Odniesienie

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

 41
Author: chaqke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 00:41:14