问题
Currently, I adopt Carrierwave for users to images.
However, I hardly find a solution for image security, i.e. how to set image authorisation for the uploaded images to only let certain user in the same group to view?
After digging Facebook's implementation, I observe that they inject these params (oh,oe, __gda_) to the image url
?oh=924eb34394&oe=55E07&__gda__=1436393492fc8bf91e1aec5
Is there any similar implementation for carrierwave or paperclip?
Thanks
回答1:
I worked quite a bit with this (only with Paperclip).
There is one solution that is okay, but it takes a lot of processing.
If you only want to hide your files from being looped through you can hash your Paperclip attachment, see this: https://github.com/thoughtbot/paperclip/wiki/Hashing
If you want to authorize user on every image load you can do like this:
Move your files out of your Public-folder
has_attached_file :image,
styles: { large: '1500x1500>', small: '250x250>'},
path: ':rails_root/storage/gallery/image/:style/:filename'
Use Sendfile to view your file
def show
send_file(object.image.path(:small), filename: object.image_file_name, type: "image/png",disposition: 'inline',x_sendfile: true)
end
I'm however a bit reluctant to implement this for example an image gallery, since it takes a GET
-action + authorization for each image. Using the x-sendfile
works with Apache to deliver the images faster.
Ref: http://apidock.com/rails/ActionController/Streaming/send_file
回答2:
I found this great solution for paperclip from https://makandracards.com/makandra/734-deliver-paperclip-attachments-to-authorized-users-only Though a little out of date, this article details everything needed to secure not only the access to attachments, but also how to secure the files themselves. This article describes all of the steps to implement it, including Capistrano deployment!
be sure to use updated routes by changing:
map.resources :notes, :member => { :attachment => :get }
to:
resources :notes, only: [] do
member do
get :attachment
end
end
also I updated the link from:
link_to 'Download attachment', [:attachment, @note]
to:
link_to 'Download Attachment', attachment_note_path( @note.id )
also see Paperclip changing URL/Path for configuring the url.
回答3:
Carrierwave stores uploads in /public
by default, where all content is simply served as static content. If you need to control access to this uploads I'd start by configuring a different storage path
class TestUploader < CarrierWave::Uploader::Base
def store_dir
Rails.root.join('uploads', relative_path).to_s
end
def serving_path # Use this method to get the serving path of the upload
File.join '/uploads', relative_path
end
private
def relative_path
File.join model.class.model_name.plural, model.id.to_s
end
end
Since CarrierWave relies on public asset serving to serve uploads, you'll have to implement your own file serving method. This is silly example of how to do that with Rails
class Test < ApplicationRecord
mount_uploader :file, TestUploader
end
Rails.application.routes.draw do
get '/uploads/:model/:id', to: 'uploads#get'
end
class UploadsController < ApplicationController
def get
# ... autorization logic
model = params.fetch(:model).singularize.camelcase.safe_constantize
return head 400 unless model.present?
send_file model.find(params.fetch(:id)).file.path
end
end
来源:https://stackoverflow.com/questions/29888708/rails-image-upload-security