Forum: Ruby on Rails How to protect images from public?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
John T. (Guest)
on 2006-06-06 06:07
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.
Daniel -. (Guest)
on 2006-06-06 07:32
(Received via mailing list)
Hi John,

There is an entry for this on the WIKI

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

Hope this is what your after
Deirdre Saoirse M. (Guest)
on 2006-06-10 01:06
(Received via mailing list)
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. :)

--
_Deirdre                                             http://deirdre.net
John T. (Guest)
on 2006-06-10 01:57
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,

<img src="/myimages/1/mypic.jpg"> 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. :)
>
> --
> _Deirdre                                             http://deirdre.net
John T. (Guest)
on 2006-06-10 01:59
Hi,
thanks for the reply.
Unfornately, that wiki was for sending a file. I'm looking for simply
serving up an <img> 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
Michael Mell (Guest)
on 2006-06-10 02:17
(Received via mailing list)
I hope this helps:
http://mcubed.name/blog/articles/2006/04/11/displa...
view-using-send_file-or-send_data

=mmell
Al E. (Guest)
on 2006-06-10 04:32
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 <img> 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
Jeff P. (Guest)
on 2006-06-10 06:27
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.  :)

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.
James L. (Guest)
on 2006-06-10 10:02
(Received via mailing list)
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
John T. (Guest)
on 2006-06-10 15:27
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/displa...
> view-using-send_file-or-send_data
>
> =mmell
This topic is locked and can not be replied to.