[1.8.x] 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.
Backport of 0f7f5bc9e7
from master
This commit is contained in:
parent
1904022f91
commit
596564e808
|
@ -53,6 +53,12 @@ def _clean_credentials(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):
|
||||
"""
|
||||
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()
|
||||
|
||||
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
|
||||
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
|
||||
# To avoid reusing another user's session, create a new, empty
|
||||
|
@ -102,7 +108,7 @@ def login(request, user):
|
|||
request.session.flush()
|
||||
else:
|
||||
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[HASH_SESSION_KEY] = session_auth_hash
|
||||
if hasattr(request, 'user'):
|
||||
|
@ -158,7 +164,7 @@ def get_user(request):
|
|||
from .models import AnonymousUser
|
||||
user = None
|
||||
try:
|
||||
user_id = request.session[SESSION_KEY]
|
||||
user_id = _get_user_session_key(request)
|
||||
backend_path = request.session[BACKEND_SESSION_KEY]
|
||||
except KeyError:
|
||||
pass
|
||||
|
|
|
@ -5,9 +5,10 @@ from .invalid_models import (
|
|||
CustomUserBadRequiredFields,
|
||||
)
|
||||
from .with_foreign_key import CustomUserWithFK, Email
|
||||
from .uuid_pk import UUIDUser
|
||||
|
||||
__all__ = (
|
||||
'CustomPermissionsUser', 'CustomUserNonUniqueUsername',
|
||||
'CustomUserNonListRequiredFields', 'CustomUserBadRequiredFields',
|
||||
'CustomUserWithFK', 'Email', 'IsActiveTestUser1',
|
||||
'CustomUserWithFK', 'Email', 'IsActiveTestUser1', 'UUIDUser',
|
||||
)
|
||||
|
|
|
@ -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'
|
|
@ -3,7 +3,9 @@ from __future__ import unicode_literals
|
|||
from datetime import date
|
||||
|
||||
from django.conf import settings
|
||||
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.hashers import MD5PasswordHasher
|
||||
from django.contrib.auth.models import AnonymousUser, Group, Permission, User
|
||||
|
@ -13,7 +15,7 @@ from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
|||
from django.http import HttpRequest
|
||||
from django.test import TestCase, modify_settings, override_settings
|
||||
|
||||
from .models import CustomPermissionsUser
|
||||
from .models import CustomPermissionsUser, UUIDUser
|
||||
|
||||
|
||||
class CountingMD5PasswordHasher(MD5PasswordHasher):
|
||||
|
@ -287,6 +289,18 @@ class CustomUserModelBackendAuthenticateTest(TestCase):
|
|||
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):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue