Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Django to prevent direct access to an image file?

Tags:

python

django

I'd like to prevent my web users from simply right clicking an image and copying/sharing the URL. Certain authenticated users have access to certain images, and I'd like to enforce this as much as possible. Non authenticated users should have no access to image files.

It's generally recommended to avoid storing/fetching images from a DB, due to performance issues, from what I have read.

I've considered having a function that reads the file (server side, in python) and inserts it into the webpage (base64 encoded, possibly, or some other way) in the Django view functions. Combined with an .htaccess file that denies external requests, this would likely work, but it seems like it'd be resource intensive.

Is there any other options for enforcing this rule? I realize users can screenshot, save images, etc, but it's my responsibility to enforce these restrictions as much as possible, what are my best options?

edit: I have no experience using a CDN, but would be willing to use this if it's a viable option that covers these needs.

like image 838
Matthew Pace Avatar asked Mar 22 '23 08:03

Matthew Pace


1 Answers

I'll bite.

Session Middleware - not elegant, but it will work

You'll want the images you don't want served publicly to not be served through your standard apache/django static files config.

your session middleware can then check all incoming requests for the path and if the path is your image directory (such as /privateimg/) and the user is not authenticated you can bounce them back out or replace it inline with another image (such as one that has a watermark).

You can check out the django docs on how session middleware works https://docs.djangoproject.com/en/dev/topics/http/sessions/

People can still pass your links around, but only authenticated users can actually see the contents of said links (called gating your content)

To elaborate:

settings.py

GATED_CONTENT = (
    '/some_content_dir/', # This is a directory we want to gate
    '.pdf', # maybe we want to gate an entire content type
)

MIDDLEWARE_CLASSES = (
    ...  # Out of the box middleware...blah blah
    'yourapp.somemodule.sessionmiddleware.GatedContent',
)

Then you have the following app structure

yourapp
   |-somemodule
        |-sessionmiddleware.py

Now to the meat (yum!)

sessionmiddleware.py

class GatedContent(object):
"""
Prevents specific content directories and types 
from being exposed to non-authenticated users
"""

def process_request(self, request):
   path = request.path
   user = request.user # out of the box auth, YMMV

   is_gated = False
   for gated in settings.GATED_CONTENT:
      if path.startswith(gated) or path.endswith(gated):
          is_gated = True
          break
  # Validate the user is an authenticated/valid user
  if is_gated and not user.is_authenticated():
      # Handle redirect

 
like image 83
Mike McMahon Avatar answered Apr 27 '23 01:04

Mike McMahon