0

I have the following problem: I wrote an application in Django, basically it’s some kind of management platform for my choir. Now we have some files that we want to provide to our members, but only to them (i.e. registered users). Additionally, there are some files that should only be accessible to the management. Ideally, I want to be able to define in the database who can access which files.

Here is some information about the environment:

  • Server OS Debian 8.7
  • Python version 2.7
  • Django version 1.10
  • Mod_wsgi version 4.3

What have I tried so far?

Django documentation provides a very, very small example of how to authenticate against the database.

The part where I only validate whether the user is a valid user works. Although it kind of sucks, since the users have to login again every time they access a file.

The part where I validate whether the user is a group doesn't work at all. Apache says:

Unknown Authz provider: group

Then I started to look up this problem, which led me here. When I use the option wsgi-group the apache configuration doesn't cause any problems, but it apparently doesn't validate whether the user is in the specified group either. (I tried to access the file with a user who is not in the specified group and succeeded...)

Now here are some questions I have to this problem:

  1. Has anyone else experienced these problems with the Require group/Require wsgi-group option and has found a solution?
  2. Is there a possibility to "link" the session of the website with the session of the apache file access? As I already mentioned, it is not very user-friendly if the users have to login again every time they want to access a file..
  3. Is there a possibility to write a custom authentication function? Technically, looking at an example implementation for the authentication method check_password (here "auth.wsgi"), I could overwrite this function, provided that the environ variable contains the URL that the user wants to access. (does it?)
  4. This would probably be the most dynamic solution, but I don't quite know if this is possible. The basic idea ist that I render a button in the view for each downloadable file, that sends a POST to the server. The server checks whether the session user has the rights to access this file, and, if true, returns the file. This would mean that the file can only be accessed by the application and not through the apache. Is this possible?

I hope someone can help me, thank you in advance anyways =)

Edit: I did some research and found an answer for my last question here (Having Django serve downloadable files). With the mod_xsendfile this is apparently manageable pretty easily. That leaves just 3 more questions ;)

Community
  • 1
  • 1

1 Answers1

0

I have also used X-Send for various purposes within my Django App (usually to serve up files stored in FileFields) but for hosting a suite of static pages such as sphinx-generated pages and supporting media, proxying via X-Send has lead me into more problems than solutions.

As I was researching my own question I discovered yours and realized that mine is the solution to your question #1 and #2: Use mod_wsgi's WSGIAccessScript config with the allow_access(environ, host) function to instantiate a Django WSGI Request which can be programatically distilled to a boolean using whatever business logic you require. I hope someone else can answer my more specific concerns about the approach, but it is functional.

Your question #3 suggests I point you towards Django's Custom Authentication Backend documentation. I have written a custom backend that uses email addresses to authenticate a user rather than requiring users to remember an arbitrary username.

#Django Imports
from django.conf import settings
from django.contrib.auth.models import User

class EmailAuthBackend(object):
    """
    Email Authentication Backend

    Allows a user to sign in using an email/password pair rather than
    a username/password pair.
    """

    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = User.objects.get(email__iexact=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None 

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
Community
  • 1
  • 1
Bram Wiebe
  • 11
  • 3