Enables cookie based authentication with apache. I needed user authentication for some static files, but couldn't use the method described here as this prompts the user for his credentials, making him log in twice. There is some overhead in the code, because it runs all request middleware components (only session and auth would be needed). All arguments described in the link above are supported. I use it like this in the apache config:
<Location "/protected/location">
PythonPath "['/path/to/proj/'] + sys.path"
PythonOption DJANGO_SETTINGS_MODULE myproj.settings
PythonOption DjangoPermissionName '<permission.codename>'
PythonAccessHandler my_proj.modpython #this should point to accesshandler
SetHandler None
</Location>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import os
from mod_python import apache
from django.core.handlers.base import BaseHandler
from django.core.handlers.modpython import ModPythonRequest
class AccessHandler(BaseHandler):
def __call__(self, req):
from django.conf import settings
# set up middleware
if self._request_middleware is None:
self.load_middleware()
# populate the request object
request = ModPythonRequest(req)
# and apply the middleware to it
# actually only session and auth middleware would be needed here
for middleware_method in self._request_middleware:
middleware_method(request)
return request
def accesshandler(req):
os.environ.update(req.subprocess_env)
# check for PythonOptions
_str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
options = req.get_options()
permission_name = options.get('DjangoPermissionName', None)
staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
if settings_module:
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
request=AccessHandler()(req)
if request.user.is_authenticated():
if superuser_only and request.user.is_superuser:
return apache.OK
elif staff_only and request.user.is_staff:
return apache.OK
elif permission_name and request.user.has_perm(permission_name):
return apache.OK
return apache.HTTP_UNAUTHORIZED
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
I assume this requires mod_python rather than say fcgi?
#
Yes, wouldn't know how to do this with fcgi. It would probably depend on which server you are using, and how you are able to define handlers for that server.
#
Hi - Thanks for the snippet! Its a real lifesaver for me.
I had to make a few modifications to get it to work for me. First "request.user.is_authenticated()" always comes back as true. I am using IE7 with cookies that expire when the browser window is closed. I solved the problem with the following code:
if request.user.is_anonymous(): return apache.HTTP_UNAUTHORIZED
added before request.user.is_authenticated().
Next, I am using the code to server static pages through apache. In my httpd.conf file, when I had the line:
SetHandler python-program
The requested ended up being served by django. I was able to get apache to serve the content by replacing that line with:
SetHandler None
My (noob) understanding of apache is that it processes the request in phases and the phase called "handler" is the last phase in the sequence. So the python access handler still gets called, but after that the request processing is completed by apache.
Chuck
#
Thanks for this snippet. I have one comment, which I hope will save some other folks time. Initially, I had this in my httpd.conf:
Which threw this lovely error:
I figured out that somehow multiple req objects were being processed by the handler at the same time, thus giving me multiple copies of the environment. I fixed this by rearranging my Location directives as so:
I'm not familiar at all with the way apache works with mod_python, but this reconfiguration of my httpd.conf makes things work as I expect them to. So I hope this helps save someone else some frustration.
-Pat
#
Please login first before commenting.