Index: django/contrib/auth/handlers/modpython.py
===================================================================
--- django/contrib/auth/handlers/modpython.py	(revision 5377)
+++ django/contrib/auth/handlers/modpython.py	(working copy)
@@ -1,52 +1,101 @@
 from mod_python import apache
 import os
+from django.core import signals
+from django.dispatch import dispatcher
+from django.core.handlers.base import BaseHandler
+from django.core.handlers.modpython import ModPythonRequest
+from django.contrib.auth import authenticate
 
+_str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
+
+class ModPythonAuthOptions:
+    def __init__(self, req):
+        options = req.get_options()
+        self.permission_name = options.get('DjangoPermissionName', None)
+        self.staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
+        self.superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
+        self.settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
+
+def setup_environment(req, options):
+    """
+    mod_python fakes the environ, and thus doesn't process SetEnv. This ensures
+    any future imports relying on settings will work.
+    """
+    os.environ.update(req.subprocess_env)
+    if options.settings_module:
+        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings_module
+
+def validate_user(user, options):
+    if not user:
+        return False
+    # Don't require an is_authenticated property, but if it's there then check it
+    if hasattr(user, 'is_authenticated') and not user.is_authenticated():
+        return False
+    # Don't require an is_active property, but if it's there then check it
+    if hasattr(user, 'is_active') and not user.is_active:
+        return False
+    if options.staff_only and not getattr(user, 'is_staff', None):
+        return False
+    if options.superuser_only and not getattr(user, 'is_superuser', None):
+        return False
+    # If a permission is required then user must have a has_perm function to validate
+    if options.permission_name and (not hasattr(user, 'has_perm') or not user.has_perm(self.permission_name)):
+        return False
+    return True
+
 def authenhandler(req, **kwargs):
     """
-    Authentication handler that checks against Django's auth database.
+    mod_python authentication handler that checks against Django's auth
+    database.
     """
+    options = ModPythonAuthOptions(req)
+    setup_environment(req, options)
 
-    # mod_python fakes the environ, and thus doesn't process SetEnv.  This fixes
-    # that so that the following import works
-    os.environ.update(req.subprocess_env)
+    dispatcher.send(signal=signals.request_started)
+    try:
+        # This populates req.user too, so it's important to do first
+        password = req.get_basic_auth_pw()
 
-    # check for PythonOptions
-    _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
+        # Get the user from any of the installed backends
+        user = authenticate(username=req.user, password=password)
 
-    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
+        # Validate the user
+        if validate_user(user, options):
+            return apache.OK
+        else:
+            return apache.HTTP_UNAUTHORIZED
+    finally:
+        dispatcher.send(signal=signals.request_finished)
 
-    from django.contrib.auth.models import User
-    from django import db
-    db.reset_queries()
+def accesshandler(req):
+    """
+    mod_python access handler that uses the contrib.auth framework (with
+    sessions and therefore requiring a session cookie).
+    """
+    options = ModPythonAuthOptions(req)
+    setup_environment(req, options)
 
-    # check that the username is valid
-    kwargs = {'username': req.user, 'is_active': True}
-    if staff_only:
-        kwargs['is_staff'] = True
-    if superuser_only:
-        kwargs['is_superuser'] = True
+    # Set up middleware, now that settings works we can do it now.
+    base_handler = BaseHandler()
+    base_handler.load_middleware()
+
+    dispatcher.send(signal=signals.request_started)
     try:
-        try:
-            user = User.objects.get(**kwargs)
-        except User.DoesNotExist:
-            return apache.HTTP_UNAUTHORIZED
-    
-        # check the password and any permission given
-        if user.check_password(req.get_basic_auth_pw()):
-            if permission_name:
-                if user.has_perm(permission_name):
-                    return apache.OK
-                else:
-                    return apache.HTTP_UNAUTHORIZED
-            else:
-                return apache.OK
+        request = ModPythonRequest(req)
+
+        # Apply request middleware
+        for middleware_method in base_handler._request_middleware:
+            response = middleware_method(request)
+            if response:
+                # If we get a response, we should probably stop processing any
+                # remaining request middleware.
+                break
+
+        # Validate the user
+        user = getattr(request, 'user', None)
+        if validate_user(user, options):
+            return apache.OK
         else:
-            return apache.HTTP_UNAUTHORIZED
+            return apache.HTTP_FORBIDDEN
     finally:
-        db.connection.close()
+        dispatcher.send(signal=signals.request_finished)
Index: docs/apache_auth.txt
===================================================================
--- docs/apache_auth.txt	(revision 5377)
+++ docs/apache_auth.txt	(working copy)
@@ -17,7 +17,7 @@
 ==================
 
 To check against Django's authorization database from a Apache configuration
-file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along
+file, you can either use mod_python's ``PythonAuthenHandler`` directive along
 with the standard ``Auth*`` and ``Require`` directives::
 
     <Location /example/>
@@ -29,6 +29,22 @@
         PythonAuthenHandler django.contrib.auth.handlers.modpython
     </Location>
 
+... or use mod_python's ``PythonAccessHandler`` directive::
+
+    <Location /example/>
+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
+        PythonAccessHandler django.contrib.auth.handlers.modpython
+    </Location>
+
+The difference between these two methods is that ``PythonAuthenHandler`` uses
+basic HTTP authentication where as ``PythonAccessHandler`` uses the built-in
+``contrib.auth`` authentication (which uses a session cookie).
+
+``PythonAuthenHandler`` will prompt the user to enter their user name and
+password (usually via a basic authentication dialog box), while
+``PythonAccessHandler`` will simply raise an Apache "Forbidden" error if the
+user is not logged in or does not have the correct authorization.
+
 By default, the authentication handler will limit access to the ``/example/``
 location to users marked as staff members.  You can use a set of
 ``PythonOption`` directives to modify this behavior:
