Fixed #24161 -- Stored the user primary key as a serialized value in the session.
This allows using a UUIDField primary key along with the JSON session serializer. Thanks to Trac alias jamesbeith for the report and Simon Charette for the initial patch.
This commit is contained in:
parent
93b3ef9b2e
commit
0f7f5bc9e7
@ -53,6 +53,12 @@ def _clean_credentials(credentials):
|
|||||||
return credentials
|
return credentials
|
||||||
|
|
||||||
|
|
||||||
|
def _get_user_session_key(request):
|
||||||
|
# This value in the session is always serialized to a string, so we need
|
||||||
|
# to convert it back to Python whenever we access it.
|
||||||
|
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
|
||||||
|
|
||||||
|
|
||||||
def authenticate(**credentials):
|
def authenticate(**credentials):
|
||||||
"""
|
"""
|
||||||
If the given credentials are valid, return a User object.
|
If the given credentials are valid, return a User object.
|
||||||
@ -93,7 +99,7 @@ def login(request, user):
|
|||||||
session_auth_hash = user.get_session_auth_hash()
|
session_auth_hash = user.get_session_auth_hash()
|
||||||
|
|
||||||
if SESSION_KEY in request.session:
|
if SESSION_KEY in request.session:
|
||||||
if request.session[SESSION_KEY] != user.pk or (
|
if _get_user_session_key(request) != user.pk or (
|
||||||
session_auth_hash and
|
session_auth_hash and
|
||||||
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
|
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
|
||||||
# To avoid reusing another user's session, create a new, empty
|
# To avoid reusing another user's session, create a new, empty
|
||||||
@ -102,7 +108,7 @@ def login(request, user):
|
|||||||
request.session.flush()
|
request.session.flush()
|
||||||
else:
|
else:
|
||||||
request.session.cycle_key()
|
request.session.cycle_key()
|
||||||
request.session[SESSION_KEY] = user.pk
|
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
|
||||||
request.session[BACKEND_SESSION_KEY] = user.backend
|
request.session[BACKEND_SESSION_KEY] = user.backend
|
||||||
request.session[HASH_SESSION_KEY] = session_auth_hash
|
request.session[HASH_SESSION_KEY] = session_auth_hash
|
||||||
if hasattr(request, 'user'):
|
if hasattr(request, 'user'):
|
||||||
@ -158,7 +164,7 @@ def get_user(request):
|
|||||||
from .models import AnonymousUser
|
from .models import AnonymousUser
|
||||||
user = None
|
user = None
|
||||||
try:
|
try:
|
||||||
user_id = request.session[SESSION_KEY]
|
user_id = _get_user_session_key(request)
|
||||||
backend_path = request.session[BACKEND_SESSION_KEY]
|
backend_path = request.session[BACKEND_SESSION_KEY]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
@ -5,9 +5,10 @@ from .invalid_models import (
|
|||||||
CustomUserBadRequiredFields,
|
CustomUserBadRequiredFields,
|
||||||
)
|
)
|
||||||
from .with_foreign_key import CustomUserWithFK, Email
|
from .with_foreign_key import CustomUserWithFK, Email
|
||||||
|
from .uuid_pk import UUIDUser
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'CustomPermissionsUser', 'CustomUserNonUniqueUsername',
|
'CustomPermissionsUser', 'CustomUserNonUniqueUsername',
|
||||||
'CustomUserNonListRequiredFields', 'CustomUserBadRequiredFields',
|
'CustomUserNonListRequiredFields', 'CustomUserBadRequiredFields',
|
||||||
'CustomUserWithFK', 'Email', 'IsActiveTestUser1',
|
'CustomUserWithFK', 'Email', 'IsActiveTestUser1', 'UUIDUser',
|
||||||
)
|
)
|
||||||
|
13
tests/auth_tests/models/uuid_pk.py
Normal file
13
tests/auth_tests/models/uuid_pk.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import uuid
|
||||||
|
|
||||||
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
from django.contrib.auth.tests.custom_user import RemoveGroupsAndPermissions
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
with RemoveGroupsAndPermissions():
|
||||||
|
class UUIDUser(AbstractUser):
|
||||||
|
"""A user with a UUID as primary key"""
|
||||||
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'auth'
|
@ -2,7 +2,9 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from django.contrib.auth import BACKEND_SESSION_KEY, authenticate, get_user
|
from django.contrib.auth import (
|
||||||
|
BACKEND_SESSION_KEY, SESSION_KEY, authenticate, get_user,
|
||||||
|
)
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from django.contrib.auth.hashers import MD5PasswordHasher
|
from django.contrib.auth.hashers import MD5PasswordHasher
|
||||||
from django.contrib.auth.models import AnonymousUser, Group, Permission, User
|
from django.contrib.auth.models import AnonymousUser, Group, Permission, User
|
||||||
@ -12,7 +14,7 @@ from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
|||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.test import TestCase, modify_settings, override_settings
|
from django.test import TestCase, modify_settings, override_settings
|
||||||
|
|
||||||
from .models import CustomPermissionsUser
|
from .models import CustomPermissionsUser, UUIDUser
|
||||||
|
|
||||||
|
|
||||||
class CountingMD5PasswordHasher(MD5PasswordHasher):
|
class CountingMD5PasswordHasher(MD5PasswordHasher):
|
||||||
@ -288,6 +290,18 @@ class CustomUserModelBackendAuthenticateTest(TestCase):
|
|||||||
self.assertEqual(test_user, authenticated_user)
|
self.assertEqual(test_user, authenticated_user)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(AUTH_USER_MODEL='auth.UUIDUser')
|
||||||
|
class UUIDUserTests(TestCase):
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
"""
|
||||||
|
A custom user with a UUID primary key should be able to login.
|
||||||
|
"""
|
||||||
|
user = UUIDUser.objects.create_user(username='uuid', password='test')
|
||||||
|
self.assertTrue(self.client.login(username='uuid', password='test'))
|
||||||
|
self.assertEqual(UUIDUser.objects.get(pk=self.client.session[SESSION_KEY]), user)
|
||||||
|
|
||||||
|
|
||||||
class TestObj(object):
|
class TestObj(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user