2010-05-02 5 views
5

Voici une histoire:Comment stocker des photos et vidéos privées Ruby on Rails

  • utilisateur A devrait être en mesure de télécharger une image.
  • L'utilisateur A doit pouvoir définir une confidentialité. ("Public" ou "Privé").
  • L'utilisateur B ne doit pas être en mesure d'accéder aux images « privées » de l'utilisateur A.

Je prévois à l'utilisateur Paperclip pour faire face aux téléchargements.

Si je stocke les images sous "RAILS_ROOT/public/images", toute personne pouvant deviner le nom des fichiers pourrait accéder aux fichiers. (par exemple, en accédant à http://example.com/public/images/uploads/john/family.png)

J'ai besoin de montrer les images en utilisant img étiquettes, donc je ne peux pas placer un fichier sauf public.

Comment puis-je m'assurer que les images d'un utilisateur ou d'un groupe ne sont pas accessibles aux autres?

(Si je ne peux pas y parvenir avec Paperclip, ce qui est une bonne solution?)

Répondre

4

j'aurais Paperclip utiliser S3 sur le back-end, définissez les fichiers téléchargés vers le privé, et ensuite utiliser "chaîne de requête demande d'authentification alternative" à générer les URL pour mes tags d'image.

http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

+0

C'est une très, très bonne idée - en particulier avec CloudFront. – Zack

+0

Oui, cela fonctionne très bien. Callmeed posté la même chose que moi en même temps, mais il montre aussi du code. Regardez bien ce qu'il a publié et réfléchissez-y sérieusement. – jdl

8

Vous pouvez faire votre sortie de serveur rails Le contenu des fichiers d'image. Ceci est fait via une action du contrôleur (la plupart des actions impriment du HTML, mais celui-ci imprimera JPG, par exemple).

Ensuite, vous pouvez utiliser votre système d'autorisation pour restreindre l'accès au niveau du contrôleur!

class ImagesController 
    #Default show Image method streams the file contents. 
    #File doesn't have to be in public/ dir 
    def show 
    send_file @image.filename, :type => @image.content_type, 
       :disposition => 'inline' 
    end 

    # Use your favorite authorization system to restrict access 
    filter_access_to :show, :require => :view, :attribute_check => :true 
end 

Dans le code HTML, vous pouvez utiliser:

<img src="/images/show/5" /> 
+0

Merci. C'est intéressant. Je vais regarder ça. –

+2

Dans ce cas, il est raisonnable de laisser le serveur web servir les fichiers envoyés par 'send_file'. Jetez un oeil à 'X-Accel-Redirect' dans Nginx ou' X-Sendfile' dans Apache. Liens utiles: [1] (http://maxresponsemedia.com/rails/nginx-x-accel-redirect-setup-in-rails-3/), [2] (http://thedataasylum.com/articles/how -rails-nginx-x-accel-redirect-travail-ensemble.html), [3] (http://airbladesoftware.com/notes/rails-nginx-x-accel-mapping), [4] (http://www.therailsway.com/2009/2/22/file-downloads-done-right/). – mrzasa

4

Voilà comment je l'ai fait dans une application similaire.

  • Stockez vos images sur Amazon S3 au lieu du système de fichiers local. Paperclip soutient cela.
  • Définissez votre: s3_permissions sur "private" dans vos options Paperclip
  • Dans votre modèle Image, définissez une méthode qui vous permet de générer une URL autorisée limitée dans le temps pour l'image.

mine ressemble à ceci:

def s3_url(style = :original, time_limit = 30.minutes) 
    self.attachment.s3.interface.get_link(attachment.s3_bucket.to_s, attachment.path(style), time_limit) 
end 
  • Vous pouvez alors afficher des images aux personnes que si elles sont autorisées à les voir (mettre en œuvre que comme bon vous semble) -et pas à se soucier les gens devinant/regardant des images privées. Cela les empêche également de transmettre des URL depuis leur expiration (l'URL contient un jeton).
  • Soyez averti qu'il faut du temps pour que votre application génère les URL autorisées pour chaque image. Donc, si vous avez plusieurs images sur une page, cela affectera le temps de chargement.
+0

Avez-vous des suggestions sur l'optimisation de cette approche pour les applications lourdes de lecture d'images? Il semble que je vais avoir beaucoup de hits app supplémentaires ... – Jared

1

Si vous souhaitez héberger vous-même des fichiers, vous pouvez procéder à l'authentification au niveau du contrôleur comme cela a été suggéré. Une de mes applications a un AssetController qui gère la diffusion de fichiers à partir du répertoire 'private', par exemple. Une chose que je voulais ajouter est que vous devriez passer en revue this guide pour configurer X-Sendfile, ce qui permettra à votre application de dire au serveur Web de gérer l'envoi des fichiers. Vous verrez une meilleure performance avec cette approche.