Reputation: 126132
I'm working on a Rails app and using the restful-authentication plugin. The app will include user images. Only users who log in will be able to browse, but I wondered if I can also restrict direct URL access to the images to only allow logged-in users.
In other words, even if you know that an image is at thesite.com/user1/foo.jpg
, you can't see that image unless you're logged in. I know this could theoretically be done in the Apache config, but the only way I know would involve manual editing of those files, which wouldn't scale.
Is this possible? Would it make more sense to just move the photos out of the public
directory? (I'm not sure if that has any performance implications, as public
is generally used for static content.)
Upvotes: 1
Views: 1990
Reputation: 2549
Just require a user for the action:
# images_controller.rb
ImagesController < ApplicationController
before_filter :require_user, :only => 'show'
def require_user
unless current_user
redirect_to root_url # or :back, or wherever
end
end
end
However, do you really mean direct access to the image not via http://yoursite.com/userfoo/bar.jpg
, but via http://yoursite.com/images/system/file/5837/bar.jpg
? Within rails, you could check the request object:
# images_controller.rb
ImagesController < ApplicationController
before_filter :require_onsite, :only => 'show'
def require_onsite
# pseudoruby, might need some massage
unless request.referer.match(/request.domain/)
redirect_to root_url
end
end
end
Upvotes: 2
Reputation: 4173
You could create a controller action for images that just returns the binary data to the user (from a source not publicly accessible) only if the user is logged in. As a preface to this, I'm a Django/Python person, not Ruby/Rails, but from what I can tell, the configuration would look like this:
map.connect ':user/:picture', :controller => 'accounts', :action => 'displayPic'
and your actual controller would look something like:
class AccountsController < ApplicationController
def image
# check if user is logged in, then
user = Account.find(params[:user])
image = get_image(user, params[:picture])
send_data(image,
:filename => "#{params[:picture]}",
:type => "image/jpeg")
end
private
def get_image(image_name)
# do something to find image
# and return the binary data
# to the action
end
end
Made this a community wiki so anyone with better Ruby/Rails skills can clean it up
Upvotes: 3