Django.htaccess static authentication
In my application, users can upload files for other users. To make the uploaded files address-only accessible, I need some sort of static file authentication system.
My idea is to create an apache guest directory for each user and restrict access to that derectory with .htaccess.
This means that every time a new django user is created, I need to create a directory and a corresponding .htaccess file in it. I know I have to do this using post_save signals on the User model, but I don't know how to create .htaccess in the user directory from python level. Can you help me?
Or maybe you have a better solution to my problem?
a source to share
Why not have a PrivateUploadedFile object that has a field for the file and a m2m relationship for all users who are allowed to read that file? Then you don't have to mess with Apache conf ...
from django.contrib.auth.models import User
from django.db import models
import hashlib
def generate_obfuscated_filename(instance, filename):
hashed_filename = hashlib.sha1(str(filename)) #you could salt this with something
return u"your/upload/path/%s.%s" % (hashed_filename, filename.split(".")[-1]) #includes original file format extension
class PrivateUploadedFile(models.Model):
file = models.FileField(upload_to=generate_obfuscated_filename)
recipients = models.ManyToManyField('User')
uploader = models.ForeignKey('User', related_name="files_uploaded")
def available_to(self, user):
#call this as my_uploaded_file_instance.available_to(request.user) or any other user object you want
return user in self.recipients.all() #NB: not partic. efficient, but can be tuned
a source to share
If Django handles authentication and authorization as usual, use Apache mod_xsendfile
to handle Apache with the actual file. Remember to upload the files to a location that cannot be accessed directly, ideally outside the Apache document root.
This question has a good example of how to implement this behavior, but it basically comes down to customizing response['X-Sendfile'] = file_path
in your view.
django-sendfile does the same, but for a few different web servers (and convenience combinations) and django-private-files is the same, but also implementsPrivateFileField
a source to share
Add a view that controls user authentication and serve the file through django's static file generation tools :
def get_file(request, some_id):
# check that the user is allowed to see the file
# obtain the file name:
path = path_from_id(some_id)
# serve the file:
return django.views.static.serve(request, path, document_root=your_doc_root)
This is a perfectly safe solution, but perhaps not ideal if you are feeding a huge amount of files this way.
Edit: The disclaimer on the django page doesn't apply here. Obviously, it would be inefficient to serve all your files with static.serve
. However, it is secure in the sense that you only serve files to the users who are allowed.
a source to share