Opened 18 months ago

Last modified 18 months ago

#34565 closed New feature

Exception will be raised when settings.PASSWORD_HASHERS changes and the check_password() method is called in an asynchronous context. — at Version 1

Reported by: Dingning Owned by: nobody
Component: contrib.auth Version: 4.2
Severity: Normal Keywords: async auth check_password
Cc: Carlton Gibson, Jon Janzen Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Dingning)

When settings.PASSWORD_HASHERS is changed and user.check_password() is called in an async context, a SynchronousOnlyOperation exception may occur.

The reason is that the check_password function will call the synchronous setter function to update the password field of the user table when the settings.PASSWORD_HASHERS is changed.

To reproduce the process:

  1. Start Django and create a user. Suppose the user's password is 123456.
  2. Close the server, modify settings.PASSWORD_HASHERS, for example, exchange the order of the first two Hashers. You can refer to django.conf.global_settings.PASSWORD_HASHERS.
  3. Start the server and call user.check_password('123456') in the asynchronous view.
  4. SynchronousOnlyOperation is raiesd.

Reference Code:

from django.http import HttpResponse
from django.contrib.auth import get_user_model


async def test_check_password(request):
    user = await get_user_model().objects.aget(id=1)
    is_correct = user.check_password('123456')

    return HttpResponse(is_correct)

Significance:

  1. When settings.PASSWORD_HASHERS changes, check_password and related functions can be called normally in an asynchronous environment.
  2. Lay the foundation for the future django.contrib.auth module to support native asynchrony.

Solution:

Add acheck_password method, this method will call the async setter function to update the password field of the user table when the settings.PASSWORD_HASHERS is changed.

Demo:

I simply implemented the solution mentioned above and put it here for reference.
https://github.com/HappyDingning/django/tree/acheck_password

Related discussions:

https://forum.djangoproject.com/t/add-async-support-for-abstractbaseuser-check-password/20364

Thanks to bigfootjon, carltongibson and UriahKingsley

Change History (1)

comment:1 by Dingning, 18 months ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top