[ruby-on-rails] S3에 데이터를 저장하고 Rails API / iOS 클라이언트를 사용하여 안전한 방식으로 사용자 액세스를 허용하는 방법은 무엇입니까?

저는 Rails와 API를 처음 작성했습니다. S3 스토리지 솔루션에 대한 도움이 필요합니다. 여기 내 문제가 있습니다.

사용자가 iOS에서 Facebook API로 로그인하는 iOS 앱용 API를 작성 중입니다. 서버는 iOS 사용자에게 Facebook이 발행 한 토큰에 대해 사용자를 검증하고 임시 세션 토큰을 발행합니다. 이 시점부터 사용자는 S3에 저장된 콘텐츠를 다운로드해야합니다. 이 콘텐츠는 사용자와 그의 친구들에게만 속합니다. 이 사용자는 같은 무리의 사람들이 액세스 할 수있는 S3에 더 많은 콘텐츠를 추가 할 수 있습니다. Facebook 그룹에 파일을 첨부하는 것과 비슷하다고 생각합니다.

사용자가 S3와 상호 작용할 수있는 방법에는 두 가지가 있습니다. 서버에 그대로 두거나 서버가 임시 S3 토큰을 발행하도록하고 (여기서 가능성은 확실하지 않음) 사용자는 S3에 직접 콘텐츠 URL을 입력 할 수 있습니다. 이 질문은 접근 방식에 대해 이야기하고 있지만 실제로는 날짜가 있습니다 (2 년 전) : iPhone 앱 및 S3에서 사진 업로드에 대한 건축 및 디자인 질문

그래서 질문 :

  • 임시 토큰이 발급 될 때 사용자가 S3의 일부 콘텐츠에만 액세스하도록 제한하는 방법이 있습니까? 어떻게 할 수 있습니까? 100,000 명 이상의 사용자가 있다고 가정합니다.
  • iOS 장치가이 콘텐츠를 직접 가져 오도록하는 것이 좋은 생각입니까?
  • 아니면 서버가 모든 콘텐츠 전달을 제어하도록해야합니까 (물론 보안 문제가 해결됨)? 연결된 사용자에게 전달하기 전에 모든 콘텐츠를 서버에 다운로드해야합니까?
  • 레일을 알고 있다면 … 페이퍼 클립과 aws-sdk gem을 사용하여 이런 설정을 할 수 있습니까?

여러 질문에 대해 사과 드리며 문제에 대한 통찰력에 감사드립니다. 감사 🙂



답변

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 분 후에 만료되며 (이 예에서는) 해당 개체에만 유효합니다.

클라이언트에 필요한 개체가 많은 경우 서명 된 URL을 많이 발급해야합니다.

아니면 서버가 모든 콘텐츠 전달을 제어하도록해야합니까 (물론 보안 문제가 해결됨)? 연결된 사용자에게 전달하기 전에 모든 콘텐츠를 서버에 다운로드해야합니까?

이는 서버가 각 객체를 다운로드해야한다는 의미가 아니라 특정 클라이언트가 S3의 특정 객체에 액세스 할 수 있도록 인증하고 권한을 부여하기 만하면됩니다.

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


답변

위의 답변은 새로운 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


답변