How to protect images from public?


#1

Hi,
I’m trying to figure out the best way to protect images uploaded by
users who may wish to keep them private.

For example, if they are uploaded in the default file_column location
(/public/blah/blah/1/) then someone can simply type the URL
http://www.blah.com/blah/blah/1 and get the image.

I can store the images in a non-public directory in the rails app (ie:
/railsapp/images/X/) but how do I get a controller to display it (with a
given layout)? Can send_data be used to display an image and associated
HTML or just the file itself?

I don’t want to store the image as a blob in the database.

Can anyone please point me in the right direction? Any help is
appreciated.

Thanks,
John.


#2

Hi John,

There is an entry for this on the WIKI

http://wiki.rubyonrails.com/rails/pages/HowtoSendFiles

Hope this is what your after


#3

On Jun 5, 2006, at 7:07 PM, John john wrote:

(with a
given layout)? Can send_data be used to display an image and
associated
HTML or just the file itself?

I don’t want to store the image as a blob in the database.

Can anyone please point me in the right direction? Any help is
appreciated.

With file_column, you just specify the prefix. e.g., in your model:

file_column :doc, :root_path => File.join
(RAILS_ROOT, “files”)

That said, I’m having issues with routes for that (because I’ve
modified routes.rb so extensively, I suspect). It uploads just fine,
though. :slight_smile:


_Deirdre http://deirdre.net


#4

Unfortunately, that won’t work (as far as I know) because the src
directory is above the root of the rails app public directory.

that is,

is actually located at
/railsapp/public/myimages/1/mypic.jpg, and not
/railsapp/myimages/1/mypic.jpg, which is the file I want to show.

If I’m wrong, please someone let me know.

If anyone knows how I can serve up a graphic without having someone
access it by enter a url, please let me know…

Would modifying the routes to redirect anyone accessing the public
folder do it? (won’t that also redirect the src url for images?)

Thanks,
John.

Deirdre Saoirse M. wrote:

On Jun 5, 2006, at 7:07 PM, John john wrote:

(with a
given layout)? Can send_data be used to display an image and
associated
HTML or just the file itself?

I don’t want to store the image as a blob in the database.

Can anyone please point me in the right direction? Any help is
appreciated.

With file_column, you just specify the prefix. e.g., in your model:

file_column :doc, :root_path => File.join
(RAILS_ROOT, “files”)

That said, I’m having issues with routes for that (because I’ve
modified routes.rb so extensively, I suspect). It uploads just fine,
though. :slight_smile:


_Deirdre http://deirdre.net


#5

Hi,
thanks for the reply.
Unfornately, that wiki was for sending a file. I’m looking for simply
serving up an tag with an image, but I don’t want that src url
accessible by someone who simply types in the url of the image.

I don’t know if that’s possible.

I can store in images in a non-public Rails directory, but then I’m not
sure how I can serve up that image from the non-public directory.

John.

Daniel ----- wrote:

Hi John,

There is an entry for this on the WIKI

http://wiki.rubyonrails.com/rails/pages/HowtoSendFiles

Hope this is what your after


#6

John john wrote:

If anyone knows how I can serve up a graphic without having someone
access it by enter a url, please let me know…

Here’s a method I’ve used for sending pictures from an arbitrary
location in the file system:

def get_pic
send_file(User.photo_file_name_for(@params[:id]),
{:disposition => ‘inline’, :type => ‘image/jpeg’})
end

You could modify that to return an image only if a user was logged in,
for example.

Obviously, photo_file_name_for() returns a file system path to the
appropriate image.

Here’s an example of the declaration in a view:

<img class=“photo” src="/users/get_pic/<%= @user.id %>" alt="<%=
@user.name

But there’s no way to stop a user from doing “Save as…” or dragging a
copy of the image off onto their desktop or taking a screenshot or…

–Al Evans


#7

Just brainstorming here.

Could you maybe just dynamically change the permissions of a file at the
moment that you are trying to display it and then re-restrict it
immediately after that? So your rails app has control over when an
image can be accessed and regular “user directed browsing” is locked
out?

Just thinking out loud, you set up two groups, one that is restrictive,
just including root and you and ruby; another group includes those but
also the web server. You normally keep the owner of all these files set
to the restrictive group. When the rails app decides it’s appropriate
to show one to somebody, it chown’s it to the less restrictive group
just long enough for the web server to grab it, then sets it back to the
restrictive group. chmod them to 7-7-0 so only a member of the files
group can access it.

Half baked idea from somebody who is a unix newbie, don’t know if such a
scheme would work or is practical to implement. I’ve probably also
screwed up some of the terminology. Hopefully if the idea has any merit
that will shine through it’s other shortfalls. :slight_smile:

jp

John john wrote:

Hi,
I’m trying to figure out the best way to protect images uploaded by
users who may wish to keep them private.

For example, if they are uploaded in the default file_column location
(/public/blah/blah/1/) then someone can simply type the URL
http://www.blah.com/blah/blah/1 and get the image.

I can store the images in a non-public directory in the rails app (ie:
/railsapp/images/X/) but how do I get a controller to display it (with a
given layout)? Can send_data be used to display an image and associated
HTML or just the file itself?

I don’t want to store the image as a blob in the database.

Can anyone please point me in the right direction? Any help is
appreciated.

Thanks,
John.


#8

I hope this helps:
http://mcubed.name/blog/articles/2006/04/11/display-images-in-a-rails-
view-using-send_file-or-send_data

=mmell


#9

On 6/9/06, Jeff P. removed_email_address@domain.invalid wrote:

Just brainstorming here.

Could you maybe just dynamically change the permissions of a file at the
moment that you are trying to display it and then re-restrict it
immediately after that? So your rails app has control over when an
image can be accessed and regular “user directed browsing” is locked
out?

Unfortunately, that opens up the race condition where a different user
could request that image during the time that it’s unrestricted and
gain access to content that he’s not supposed to. Or the Ruby process
could die right after unlocking the file, leaving it open for
everyone.

– James


#10

Michael,

Thank you very much!! This is exactly what I was looking for.
It’s just now a simple matter of putting some session authentication
around the generate_image to protect it from prying eyes.

Thanks a lot for the link!

I’ll posted updated code on my blog.

John.

Michael Mell wrote:

I hope this helps:
http://mcubed.name/blog/articles/2006/04/11/display-images-in-a-rails-
view-using-send_file-or-send_data

=mmell