mirror of
https://github.com/django/django.git
synced 2025-08-03 18:38:50 +00:00
Fixed #21649 -- Added optional invalidation of sessions when user password changes.
Thanks Paul McMillan, Aymeric Augustin, and Erik Romijn for reviews.
This commit is contained in:
parent
9494f29d4f
commit
fd23c06023
12 changed files with 246 additions and 6 deletions
|
@ -591,6 +591,13 @@ The following methods are available on any subclass of
|
|||
:meth:`~django.contrib.auth.models.AbstractBaseUser.set_unusable_password()` has
|
||||
been called for this user.
|
||||
|
||||
.. method:: models.AbstractBaseUser.get_session_auth_hash()
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
Returns an HMAC of the password field. Used for
|
||||
:ref:`session-invalidation-on-password-change`.
|
||||
|
||||
You should also define a custom manager for your ``User`` model. If your
|
||||
``User`` model defines ``username``, ``email``, ``is_staff``, ``is_active``,
|
||||
``is_superuser``, ``last_login``, and ``date_joined`` fields the same as
|
||||
|
|
|
@ -111,6 +111,12 @@ Django also provides :ref:`views <built-in-auth-views>` and :ref:`forms
|
|||
<built-in-auth-forms>` that may be used to allow users to change their own
|
||||
passwords.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
Changing a user's password will log out all their sessions if the
|
||||
:class:`~django.contrib.auth.middleware.SessionAuthenticationMiddleware` is
|
||||
enabled. See :ref:`session-invalidation-on-password-change` for details.
|
||||
|
||||
Authenticating Users
|
||||
--------------------
|
||||
|
||||
|
@ -575,6 +581,71 @@ To apply a permission to a :doc:`class-based generic view
|
|||
:ref:`decorating-class-based-views` for details. Another approach is to
|
||||
:ref:`write a mixin that wraps as_view() <mixins_that_wrap_as_view>`.
|
||||
|
||||
.. _session-invalidation-on-password-change:
|
||||
|
||||
Session invalidation on password change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
.. warning::
|
||||
|
||||
This protection only applies if
|
||||
:class:`~django.contrib.auth.middleware.SessionAuthenticationMiddleware`
|
||||
is enabled in :setting:`MIDDLEWARE_CLASSES`. It's included if
|
||||
``settings.py`` was generated by :djadmin:`startproject` on Django ≥ 1.7.
|
||||
|
||||
If your :setting:`AUTH_USER_MODEL` inherits from
|
||||
:class:`~django.contrib.auth.models.AbstractBaseUser` or implements its own
|
||||
:meth:`~django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash()`
|
||||
method, authenticated sessions will include the hash returned by this function.
|
||||
In the :class:`~django.contrib.auth.models.AbstractBaseUser` case, this is an
|
||||
HMAC of the password field. If the
|
||||
:class:`~django.contrib.auth.middleware.SessionAuthenticationMiddleware` is
|
||||
enabled, Django verifies that the hash sent along with each request matches
|
||||
the one that's computed server-side. This allows a user to log out all of their
|
||||
sessions by changing their password.
|
||||
|
||||
The default password change views included with Django,
|
||||
:func:`django.contrib.auth.views.password_change` and the
|
||||
``user_change_password`` view in the :mod:`django.contrib.auth` admin, update
|
||||
the session with the new password hash so that a user changing their own
|
||||
password won't log themselves out. If you have a custom password change view
|
||||
and wish to have similar behavior, use this function:
|
||||
|
||||
.. function:: update_session_auth_hash(request, user)
|
||||
|
||||
This function takes the current request and the updated user object from
|
||||
which the new session hash will be derived and updates the session hash
|
||||
appropriately. Example usage::
|
||||
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
|
||||
def password_change(request):
|
||||
if request.method == 'POST':
|
||||
form = PasswordChangeForm(user=request.user, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
update_session_auth_hash(request, form.user)
|
||||
else:
|
||||
...
|
||||
|
||||
If you are upgrading an existing site and wish to enable this middleware without
|
||||
requiring all your users to re-login afterward, you should first upgrade to
|
||||
Django 1.7 and run it for a while so that as sessions are naturally recreated
|
||||
as users login, they include the session hash as described above. Once you
|
||||
start running your site with
|
||||
:class:`~django.contrib.auth.middleware.SessionAuthenticationMiddleware`, any
|
||||
users who have not logged in and had their session updated with the verification
|
||||
hash will have their existing session invalidated and be required to login.
|
||||
|
||||
.. note::
|
||||
|
||||
Since
|
||||
:meth:`~django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash()`
|
||||
is based on :setting:`SECRET_KEY`, updating your site to use a new secret
|
||||
will invalidate all existing sessions.
|
||||
|
||||
.. _built-in-auth-views:
|
||||
|
||||
Authentication Views
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue