mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	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:
		| @@ -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', | ||||
| ) | ||||
|   | ||||
							
								
								
									
										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 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 | ||||
| @@ -12,7 +14,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): | ||||
| @@ -288,6 +290,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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user