diff --git a/django/contrib/auth/handlers/modwsgi.py b/django/contrib/auth/handlers/modwsgi.py index 0e543ef368..3229c6714b 100644 --- a/django/contrib/auth/handlers/modwsgi.py +++ b/django/contrib/auth/handlers/modwsgi.py @@ -1,4 +1,4 @@ -from django.contrib.auth.models import User +from django.contrib import auth from django import db from django.utils.encoding import force_bytes @@ -11,14 +11,21 @@ def check_password(environ, username, password): on whether the user exists and authenticates. """ + UserModel = auth.get_user_model() # db connection state is managed similarly to the wsgi handler # as mod_wsgi may call these functions outside of a request/response cycle db.reset_queries() try: try: - user = User.objects.get(username=username, is_active=True) - except User.DoesNotExist: + user = UserModel.objects.get_by_natural_key(username) + except UserModel.DoesNotExist: + return None + try: + if not user.is_active: + return None + except AttributeError as e: + # a custom user may not support is_active return None return user.check_password(password) finally: @@ -30,14 +37,20 @@ def groups_for_user(environ, username): Authorizes a user based on groups """ + UserModel = auth.get_user_model() db.reset_queries() try: try: - user = User.objects.get(username=username, is_active=True) - except User.DoesNotExist: + user = UserModel.objects.get_by_natural_key(username) + except UserModel.DoesNotExist: + return [] + try: + if not user.is_active: + return [] + except AttributeError as e: + # a custom user may not support is_active return [] - return [force_bytes(group.name) for group in user.groups.all()] finally: db.close_connection() diff --git a/django/contrib/auth/tests/handlers.py b/django/contrib/auth/tests/handlers.py index 190fcee9fa..a867aae47a 100644 --- a/django/contrib/auth/tests/handlers.py +++ b/django/contrib/auth/tests/handlers.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user from django.contrib.auth.models import User, Group +from django.contrib.auth.tests.utils import skipIfCustomUser from django.test import TransactionTestCase @@ -13,7 +14,6 @@ class ModWsgiHandlerTestCase(TransactionTestCase): def setUp(self): user1 = User.objects.create_user('test', 'test@example.com', 'test') User.objects.create_user('test1', 'test1@example.com', 'test1') - group = Group.objects.create(name='test_group') user1.groups.add(group) @@ -21,6 +21,10 @@ class ModWsgiHandlerTestCase(TransactionTestCase): """ Verify that check_password returns the correct values as per http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms#Apache_Authentication_Provider + + because the custom user available in the test framework does not + support the is_active attribute, we can't test this with a custom + user. """ # User not in database @@ -32,6 +36,7 @@ class ModWsgiHandlerTestCase(TransactionTestCase): # Valid user with incorrect password self.assertFalse(check_password({}, 'test', 'incorrect')) + @skipIfCustomUser def test_groups_for_user(self): """ Check that groups_for_user returns correct values as per diff --git a/docs/howto/deployment/wsgi/apache-auth.txt b/docs/howto/deployment/wsgi/apache-auth.txt index d6594d194f..5f700f1cb3 100644 --- a/docs/howto/deployment/wsgi/apache-auth.txt +++ b/docs/howto/deployment/wsgi/apache-auth.txt @@ -14,6 +14,14 @@ version >= 2.2 and mod_wsgi >= 2.0. For example, you could: * Allow certain users to connect to a WebDAV share created with mod_dav_. +.. note:: + If you have installed a :ref:`custom User model ` and + want to use this default auth handler, it must support an `is_active` + attribute. If you want to use group based authorization, your custom user + must have a relation named 'groups', referring to a related object that has + a 'name' field. You can also specify your own custom mod_wsgi + auth handler if your custom cannot conform to these requirements. + .. _Subversion: http://subversion.tigris.org/ .. _mod_dav: http://httpd.apache.org/docs/2.2/mod/mod_dav.html