S3にデータを保存し、rails API / iOSクライアントを使用して安全な方法でユーザーアクセスを許可する方法


93

RailsとAPIを書くのは初めてです。S3ストレージソリューションについてサポートが必要です。これが私の問題です。

ユーザーがiOS上のFacebook APIでログインするiOSアプリのAPIを書いています。サーバーは、FacebookがiOSユーザーに発行するトークンに対してユーザーを検証し、一時的なセッショントークンを発行します。この時点から、ユーザーはS3に保存されているコンテンツをダウンロードする必要があります。このコンテンツは、ユーザーとその友達のサブセットにのみ属します。このユーザーは、S3にさらに多くのコンテンツを追加できます。このコンテンツは、同じ束の人々がアクセスできます。ファイルをFacebookグループに添付するのに似ていると思います...

ユーザーがS3とやり取りする方法は2つあります。サーバーに任せるか、サーバーに一時的なS3トークンを発行させ(ここでの可能性は不明)、ユーザーはコンテンツURLを直接S3に到達させることができます。私はアプローチについて話しているこの質問を見つけました、しかしそれは本当に(2年前に)日付が付けられました:iPhoneアプリとS3からの写真のアップロードに関するアーキテクチャとデザインの質問

だから質問:

  • 一時的なトークンが発行されたときに、ユーザーがS3の一部のコンテンツのみにアクセスすることを制限する方法はありますか?これどうやってするの?10万人以上のユーザーがいるとします。
  • iOSデバイスにこのコンテンツを直接引き出しさせるのは良い考えですか?
  • または、サーバーにすべてのコンテンツの受け渡しを制御させる必要があります(これにより、もちろんセキュリティが解決されます)?これは、接続されているユーザーにコンテンツを渡す前に、すべてのコンテンツをサーバーにダウンロードする必要があることを意味しますか?
  • レールを知っている場合...ペーパークリップとaws-sdkジェムを使用してこのような設定を実現できますか?

複数の質問についてお詫び申し上げます。問題についての洞察はありがたいです。ありがとう:)


1
これを見つけて、docs.aws.amazon.com
AmazonS3 /

回答:


113

aws-sdk gemを使用すると、次の呼び出しにより、S3オブジェクトの一時的な署名付きURLを取得できます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

これにより、S3のそのオブジェクトに対してのみ、署名された一時的な使用URLが提供されます。(この例では)20分後に期限切れになり、その1つのオブジェクトに対してのみ有効です。

クライアントに必要なオブジェクトがたくさんある場合は、たくさんの署名付きURLを発行する必要があります。

または、サーバーにすべてのコンテンツの受け渡しを制御させる必要があります(これにより、もちろんセキュリティが解決されます)?これは、接続されているユーザーにコンテンツを渡す前に、すべてのコンテンツをサーバーにダウンロードする必要があることを意味しますか?

これは、サーバーが各オブジェクトをダウンロードする必要があることを意味するのではなく、S3内の特定のオブジェクトにアクセスするために特定のクライアントを認証および承認するだけでよいことに注意してください。

AmazonのAPIドキュメント:https : //docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth


3
その@ejdyksenをありがとう。私が考案したソリューションはまさにそれを使用しました(私は私の答えで質問を更新していません)!したがって、私の解決策は、GETリクエストに対して認証済みURLを実行することでした。ただし、ユーザーがコンテンツを提供する場合、/ bucket / user / *書き込みアクセスを許可するポリシーがアタッチされたフェデレーテッドIAMトークン(期限切れの一時的な認証情報)を使用して、特定の/ bucket / user / objectnameロケーションにリソースを作成します。したがって、システム内のユーザーは他のユーザーのコンテンツに害を及ぼすことはできません。大丈夫と思われる。あなたの答えに感謝します。
dineth

5
:あなたは、AWS-SDK-ルビーのV2、方法は多少異なりますので注意してください使用している場合はdocs.aws.amazon.com/sdkforruby/api/Aws/S3/...
vijucat

2
ユーザーが私のアクセスキーを見ることができるのは危険ではありませんか?秘密鍵もあります(変換済み)
user2503775

3
@Dennis要点は、ファイルがサーバーにヒットする必要がないことです。リンクにはAWS認証情報が含まれていません。それは含まれているかもしれませんがACCESS_KEY_ID(私は頭の上から覚えていません)、それは秘密であることを意図していません。
ejdyksen

2
@ejdyksenおっしゃるとおり、URLにのみが含まれていることを確認しましたAWS_ACCESS_KEY_ID。もともとAWS_SECRET_ACCESS_KEY表示されていると思っていましたが、表示されていません。
デニス

46

上記の回答では、新しいaws-sdk-resourcesバージョン2ではなく、古いaws-sdk-v1 gemを使用しています。

新しい方法は次のとおりです。

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


1
expires_inデータは秒の形式であると想定しています。必ず最初に変換してください。
frillybob

「ArgumentError(期待される:expires_inは秒数)」
リードウルフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.