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 Initial Version
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
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:
- Start Django and create a user. Suppose the user's password is 123456.
- Close the server, modify
settings.PASSWORD_HASHERS
, for example, exchange the order of the first two Hashers. You can refer todjango.conf.global_settings.PASSWORD_HASHERS
. - Start the server and call
user.check_password('123456')
in the asynchronous view. 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:
- When
settings.PASSWORD_HASHERS
changes,check_password
and related functions can be called normally in an asynchronous environment. - 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