webentwicklung-frage-antwort-db.com.de

Wie speichere ich Daten in S3 und erlaube den Benutzern einen sicheren Zugriff mit Rails API / iOS-Client?

Ich bin neu im Schreiben von Rails und APIs. Ich benötige Hilfe bei der S3-Speicherlösung. Hier ist mein Problem.

Ich schreibe eine API für eine iOS-App, bei der sich die Benutzer mit der Facebook-API unter iOS anmelden. Der Server überprüft den Benutzer anhand des Tokens, das Facebook dem iOS-Benutzer ausstellt, und stellt ein temporäres Sitzungstoken aus. Ab diesem Zeitpunkt muss der Benutzer Inhalte herunterladen, die in S3 gespeichert sind. Dieser Inhalt gehört nur dem Benutzer und einer Teilmenge seiner Freunde. Dieser Benutzer kann S3 weitere Inhalte hinzufügen, auf die von derselben Gruppe von Personen zugegriffen werden kann. Ich denke, es ist ähnlich wie das Anhängen einer Datei an eine Facebook-Gruppe ...

Es gibt zwei Möglichkeiten, wie ein Benutzer mit S3 interagieren kann: Überlassen Sie es dem Server oder lassen Sie den Server ein temporäres S3-Token ausstellen (nicht sicher, welche Möglichkeiten es gibt), und der Benutzer kann die Inhalts-URLs direkt zu S3 abrufen. Ich fand diese Frage, die sich auf die Ansätze bezog, jedoch wirklich veraltet (vor 2 Jahren): Architektur- und Designfrage zum Hochladen von Fotos von der iPhone-App und S

Also die Fragen:

  • Gibt es eine Möglichkeit, einen Benutzer auf den Zugriff auf bestimmte Inhalte in S3 zu beschränken, wenn ein temporäres Token ausgegeben wird? Wie kann ich das machen? Angenommen, es gibt 100.000 oder mehr Benutzer.
  • Ist es eine gute Idee, diese Inhalte vom iOS-Gerät direkt abrufen zu lassen?
  • Oder sollte der Server den gesamten Inhalt kontrollieren lassen (dies löst natürlich die Sicherheit)? Bedeutet dies, dass ich alle Inhalte auf den Server herunterladen muss, bevor ich sie an die verbundenen Benutzer weitergebe?
  • Wenn Sie Rails kennen ... kann ich Paperclip- und aws-sdk-Edelsteine ​​verwenden, um dieses Setup zu erreichen?

Entschuldigung für mehrere Fragen und ich freue mich über jeden Einblick in das Problem. Vielen Dank :)

91
dineth

Mit dem aws-sdk gem können Sie eine temporär signierte URL für jedes S3-Objekt abrufen, indem Sie 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

Dadurch erhalten Sie eine signierte, temporäre Verwendungs-URL nur für dieses Objekt in S3. Es läuft nach 20 Minuten ab (in diesem Beispiel) und ist nur für dieses eine Objekt geeignet.

Wenn Sie viele Objekte haben, die der Client benötigt, müssen Sie viele signierte URLs ausgeben.

Oder sollte der Server den gesamten Inhalt kontrollieren lassen (dies löst natürlich die Sicherheit)? Bedeutet dies, dass ich alle Inhalte auf den Server herunterladen muss, bevor ich sie an die verbundenen Benutzer weitergebe?

Beachten Sie, dass dies nicht bedeutet, dass der Server jedes Objekt herunterladen muss, sondern nur bestimmte Clients authentifizieren und autorisieren muss, um auf bestimmte Objekte in S3 zuzugreifen.

API-Dokumente von Amazon: https://docs.aws.Amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

113
ejdyksen

Die obigen Antworten verwenden das alte Juwel aws-sdk-v1 und nicht die neue Version 2 von aws-sdk-resources.

Der neue Weg ist:

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

dabei ist Ihr_Objektschlüssel der Pfad zu Ihrer Datei. Wenn Sie das nachschlagen müssen, würden Sie Folgendes verwenden:

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

Diese Informationen waren erschreckend schwer zu finden, und ich habe fast aufgegeben und den älteren Edelstein benutzt.

Referenz

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

45
chaqke