Refs #25847 -- Added system check for UserModel.is_anonymous/is_authenticated methods.

This commit is contained in:
Tim Graham 2016-05-05 12:42:19 -04:00
parent b3acf35f13
commit 03efa304bc
3 changed files with 60 additions and 0 deletions

View File

@ -6,6 +6,7 @@ from itertools import chain
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core import checks from django.core import checks
from django.utils import six
from .management import _get_builtin_permissions from .management import _get_builtin_permissions
@ -73,6 +74,26 @@ def check_user_model(app_configs=None, **kwargs):
) )
) )
if isinstance(cls().is_anonymous, six.types.MethodType):
errors.append(
checks.Critical(
'%s.is_anonymous must be an attribute or property rather than '
'a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % cls,
obj=cls,
id='auth.C009',
)
)
if isinstance(cls().is_authenticated, six.types.MethodType):
errors.append(
checks.Critical(
'%s.is_authenticated must be an attribute or property rather '
'than a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % cls,
obj=cls,
id='auth.C010',
)
)
return errors return errors

View File

@ -450,6 +450,12 @@ Auth
to be at most 255 characters. to be at most 255 characters.
* **auth.E008**: The permission named ``<name>`` of model ``<model>`` is longer * **auth.E008**: The permission named ``<name>`` of model ``<model>`` is longer
than 255 characters. than 255 characters.
* **auth.C009**: ``<User model>.is_anonymous`` must be an attribute or property
rather than a method. Ignoring this is a security issue as anonymous users
will be treated as authenticated!
* **auth.C010**: ``<User model>.is_authenticated`` must be an attribute or
property rather than a method. Ignoring this is a security issue as anonymous
users will be treated as authenticated!
Content Types Content Types

View File

@ -83,6 +83,39 @@ class UserModelChecksTests(SimpleTestCase):
), ),
]) ])
@override_settings(AUTH_USER_MODEL='auth_tests.BadUser')
def test_is_anonymous_authenticated_methods(self):
"""
<User Model>.is_anonymous/is_authenticated must not be methods.
"""
class BadUser(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
USERNAME_FIELD = 'username'
def is_anonymous(self):
return True
def is_authenticated(self):
return True
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Critical(
'%s.is_anonymous must be an attribute or property rather than '
'a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % BadUser,
obj=BadUser,
id='auth.C009',
),
checks.Critical(
'%s.is_authenticated must be an attribute or property rather '
'than a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % BadUser,
obj=BadUser,
id='auth.C010',
),
])
@isolate_apps('auth_tests', attr_name='apps') @isolate_apps('auth_tests', attr_name='apps')
@override_system_checks([check_models_permissions]) @override_system_checks([check_models_permissions])