Veriler S3'te nasıl saklanır ve rails API / iOS istemcisi ile güvenli bir şekilde kullanıcı erişimine nasıl izin verilir?


93

Rails ve API'leri yazma konusunda yeniyim. S3 depolama çözümüyle ilgili yardıma ihtiyacım var. İşte benim sorunum.

Kullanıcıların iOS'ta Facebook API ile oturum açtığı bir iOS uygulaması için bir API yazıyorum. Sunucu, kullanıcıyı, iOS kullanıcısına Facebook belirtecine karşı doğrular ve geçici bir Oturum belirteci verir. Bu noktadan sonra kullanıcının S3'te depolanan içeriği indirmesi gerekir. Bu içerik yalnızca kullanıcıya ve arkadaşlarının bir alt kümesine aittir. Bu kullanıcı, aynı grup tarafından erişilebilen S3'e daha fazla içerik ekleyebilir. Sanırım bir Facebook grubuna dosya eklemeye benziyor ...

Bir kullanıcının S3 ile etkileşimde bulunmasının 2 yolu vardır ... bunu sunucuya bırakabilir veya sunucunun geçici bir S3 jetonu vermesini sağlayabilirsiniz (buradaki olasılıklardan emin değilsiniz) ve kullanıcı içerik URL'lerine doğrudan S3'e ulaşabilir. Bu soruyu yaklaşımlardan bahsederken buldum, ancak gerçekten tarihli (2 yıl önce): iPhone uygulaması ve S3'ten fotoğraf yüklemekle ilgili mimari ve tasarım sorusu

Yani sorular:

  • Geçici bir jeton verildiğinde bir kullanıcıyı yalnızca S3'teki bazı içeriklere erişimle sınırlamanın bir yolu var mı? Bunu nasıl yapabilirim? Diyelim ki ... 100.000 veya daha fazla kullanıcı var.
  • İOS cihazının bu içeriği doğrudan çekmesine izin vermek iyi bir fikir mi?
  • Veya sunucunun tüm içerik geçişini kontrol etmesine izin mi vermelisiniz (bu elbette güvenliği çözer)? Bu, bağlı kullanıcılara teslim etmeden önce tüm içeriği sunucuya indirmem gerektiği anlamına mı geliyor?
  • Rayları biliyorsanız ... bu tür bir kurulumu elde etmek için ataç ve aws-sdk mücevherleri kullanabilir miyim?

Birden fazla soru için özür dilerim ve sorunla ilgili her türlü içgörüyü takdir ediyorum. Teşekkürler :)


Yanıtlar:


113

Aws-sdk gem'i kullanarak, herhangi bir S3 nesnesi için geçici olarak imzalanmış bir url alabilirsiniz 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

Bu size yalnızca S3'teki nesne için imzalı, geçici kullanım URL'si verecektir. 20 dakika sonra sona erer (bu örnekte) ve yalnızca bu tek nesne için iyidir.

Müşterinin ihtiyaç duyduğu çok sayıda nesneye sahipseniz, çok sayıda imzalanmış URL yayınlamanız gerekir.

Veya sunucunun tüm içerik geçişini kontrol etmesine izin mi vermelisiniz (bu elbette güvenliği çözer)? Bu, bağlı kullanıcılara teslim etmeden önce tüm içeriği sunucuya indirmem gerektiği anlamına mı geliyor?

Bunun, sunucunun her nesneyi indirmesi gerektiği anlamına gelmediğini, yalnızca belirli istemcileri S3'teki belirli nesnelere erişmeleri için doğrulaması ve yetkilendirmesi gerektiğini unutmayın.

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


3
Bunun için teşekkürler @ejdyksen. Tasarladığım çözüm tam olarak bunu kullandı (soruyu cevabımla güncellemedim)! Benim çözümüm GET istekleri için kimliği doğrulanmış URL'ler yapmaktı. Bununla birlikte, bir kullanıcı içeriğe katkıda bulunduğunda, / klasör / kullanıcı / * yazma erişimine izin vermek için eklenmiş ilkeyle birleşik IAM jetonunu (süresi dolan geçici kimlik bilgileri) kullanarak belirli bir / paket / kullanıcı / nesne adı konumuna kaynaklar oluşturur. böylece sistemdeki hiçbir kullanıcı diğer kullanıcıların içeriğine zarar veremez. İyi çalışıyor gibi görünüyor. Cevabınızı takdir edin.
yemek


2
Kullanıcının erişim anahtarımı görebilmesi bir risk değil mi? Ayrıca gizli anahtar da var (dönüştürülmüş)
user2503775

3
@Dennis, dosyanın sunucunuza vurmasına gerek olmamasıdır. Bağlantı, AWS kimlik bilgilerinizi içermiyor. ACCESS_KEY_ID(Kafamın üst kısmını hatırlamıyorum) içerebilir , ancak bu bir sır olarak düşünülmemiştir.
ejdyksen

2
@ejdyksen haklısınız, az önce URL'nin yalnızca AWS_ACCESS_KEY_ID. Başlangıçta bunun AWS_SECRET_ACCESS_KEYda görüntülendiğini sanıyordum ama değil.
Dennis

47

Yukarıdaki yanıtlar, yeni aws-sdk-resources sürüm 2 yerine eski aws-sdk-v1 gemini kullanır.

Yeni yol şudur:

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

Nesne_anahtarınız dosyanızın yoludur. Buna bakmanız gerekirse, aşağıdaki gibi bir şey kullanırsınız:

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

Bu bilgiyi kazmak şaşırtıcı derecede zordu ve neredeyse pes edip eski mücevheri kullandım.

Referans

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


1
expires_inveriyi saniyeler halinde bekliyor, sadece önce onu dönüştürdüğünüzden emin olun.
frillybob

"ArgumentError (beklenen: birkaç saniye olacak şekilde sona eriyor)"
Nikita Fedyashev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.