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


93

저는 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을 사용하여 이런 설정을 할 수 있습니까?

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


답변:


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

클라이언트에 필요한 개체가 많은 경우 서명 된 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-ruby 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그것도 전시되어 있다고 생각 했지만 그렇지 않습니다.
Dennis

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은 몇 초가 될 것으로 예상 됨)"
reedwolf
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.