Ticket #3583: apache_auth.patch
File apache_auth.patch, 7.2 KB (added by , 17 years ago) |
---|
-
django/contrib/auth/handlers/modpython.py
1 1 from mod_python import apache 2 2 import os 3 from django.core import signals 4 from django.dispatch import dispatcher 5 from django.core.handlers.base import BaseHandler 6 from django.core.handlers.modpython import ModPythonRequest 7 from django.contrib.auth import authenticate 3 8 9 _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes') 10 11 class ModPythonAuthOptions: 12 def __init__(self, req): 13 options = req.get_options() 14 self.permission_name = options.get('DjangoPermissionName', None) 15 self.staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on")) 16 self.superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off")) 17 self.settings_module = options.get('DJANGO_SETTINGS_MODULE', None) 18 19 def setup_environment(req, options): 20 """ 21 mod_python fakes the environ, and thus doesn't process SetEnv. This ensures 22 any future imports relying on settings will work. 23 """ 24 os.environ.update(req.subprocess_env) 25 if options.settings_module: 26 os.environ['DJANGO_SETTINGS_MODULE'] = options.settings_module 27 28 def validate_user(user, options): 29 if not user: 30 return False 31 # Don't require an is_authenticated property, but if it's there then check it 32 if hasattr(user, 'is_authenticated') and not user.is_authenticated(): 33 return False 34 # Don't require an is_active property, but if it's there then check it 35 if hasattr(user, 'is_active') and not user.is_active: 36 return False 37 if options.staff_only and not getattr(user, 'is_staff', None): 38 return False 39 if options.superuser_only and not getattr(user, 'is_superuser', None): 40 return False 41 # If a permission is required then user must have a has_perm function to validate 42 if options.permission_name and (not hasattr(user, 'has_perm') or not user.has_perm(self.permission_name)): 43 return False 44 return True 45 4 46 def authenhandler(req, **kwargs): 5 47 """ 6 Authentication handler that checks against Django's auth database. 48 mod_python authentication handler that checks against Django's auth 49 database. 7 50 """ 51 options = ModPythonAuthOptions(req) 52 setup_environment(req, options) 8 53 9 # mod_python fakes the environ, and thus doesn't process SetEnv. This fixes 10 # that so that the following import works 11 os.environ.update(req.subprocess_env) 54 dispatcher.send(signal=signals.request_started) 55 try: 56 # This populates req.user too, so it's important to do first 57 password = req.get_basic_auth_pw() 12 58 13 # check for PythonOptions14 _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')59 # Get the user from any of the installed backends 60 user = authenticate(username=req.user, password=password) 15 61 16 options = req.get_options()17 permission_name = options.get('DjangoPermissionName', None)18 staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))19 superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))20 settings_module = options.get('DJANGO_SETTINGS_MODULE', None)21 if settings_module:22 os.environ['DJANGO_SETTINGS_MODULE'] = settings_module62 # Validate the user 63 if validate_user(user, options): 64 return apache.OK 65 else: 66 return apache.HTTP_UNAUTHORIZED 67 finally: 68 dispatcher.send(signal=signals.request_finished) 23 69 24 from django.contrib.auth.models import User 25 from django import db 26 db.reset_queries() 70 def accesshandler(req): 71 """ 72 mod_python access handler that uses the contrib.auth framework (with 73 sessions and therefore requiring a session cookie). 74 """ 75 options = ModPythonAuthOptions(req) 76 setup_environment(req, options) 27 77 28 # check that the username is valid 29 kwargs = {'username': req.user, 'is_active': True} 30 if staff_only: 31 kwargs['is_staff'] = True 32 if superuser_only: 33 kwargs['is_superuser'] = True 78 # Set up middleware, now that settings works we can do it now. 79 base_handler = BaseHandler() 80 base_handler.load_middleware() 81 82 dispatcher.send(signal=signals.request_started) 34 83 try: 35 try:36 user = User.objects.get(**kwargs) 37 except User.DoesNotExist:38 return apache.HTTP_UNAUTHORIZED39 40 # check the password and any permission given41 if user.check_password(req.get_basic_auth_pw()):42 if permission_name:43 if user.has_perm(permission_name):44 return apache.OK 45 else:46 return apache.HTTP_UNAUTHORIZED47 else:48 84 request = ModPythonRequest(req) 85 86 # Apply request middleware 87 for middleware_method in base_handler._request_middleware: 88 response = middleware_method(request) 89 if response: 90 # If we get a response, we should probably stop processing any 91 # remaining request middleware. 92 break 93 94 # Validate the user 95 user = getattr(request, 'user', None) 96 if validate_user(user, options): 97 return apache.OK 49 98 else: 50 return apache.HTTP_ UNAUTHORIZED99 return apache.HTTP_FORBIDDEN 51 100 finally: 52 d b.connection.close()101 dispatcher.send(signal=signals.request_finished) -
docs/apache_auth.txt
17 17 ================== 18 18 19 19 To check against Django's authorization database from a Apache configuration 20 file, you 'll need touse mod_python's ``PythonAuthenHandler`` directive along20 file, you can either use mod_python's ``PythonAuthenHandler`` directive along 21 21 with the standard ``Auth*`` and ``Require`` directives:: 22 22 23 23 <Location /example/> … … 29 29 PythonAuthenHandler django.contrib.auth.handlers.modpython 30 30 </Location> 31 31 32 ... or use mod_python's ``PythonAccessHandler`` directive:: 33 34 <Location /example/> 35 SetEnv DJANGO_SETTINGS_MODULE mysite.settings 36 PythonAccessHandler django.contrib.auth.handlers.modpython 37 </Location> 38 39 The difference between these two methods is that ``PythonAuthenHandler`` uses 40 basic HTTP authentication where as ``PythonAccessHandler`` uses the built-in 41 ``contrib.auth`` authentication (which uses a session cookie). 42 43 ``PythonAuthenHandler`` will prompt the user to enter their user name and 44 password (usually via a basic authentication dialog box), while 45 ``PythonAccessHandler`` will simply raise an Apache "Forbidden" error if the 46 user is not logged in or does not have the correct authorization. 47 32 48 By default, the authentication handler will limit access to the ``/example/`` 33 49 location to users marked as staff members. You can use a set of 34 50 ``PythonOption`` directives to modify this behavior: