Django password reset: new password must be different from any of the last four user passwords

I am new to Django, please help me how to implement the Reset password so that the new password is different from any of the last four passwords sent by the user to django:

I'm using the default django password reset: urls.py:

url(r'^password/reset/$',auth_views.password_reset,      
          name='auth_password_reset'),

      

Django / vno / auto / views.py:

@csrf_protect
def password_reset(request, is_admin_site=False,
                   template_name='registration/password_reset_form.html',
                   email_template_name='registration/password_reset_email.html',
                   subject_template_name='registration/password_reset_subject.txt',
                   password_reset_form=PasswordResetForm,
                   token_generator=default_token_generator,
                   post_reset_redirect=None,
                   from_email=None,
                   current_app=None,
                   extra_context=None):
    if post_reset_redirect is None:
        post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done')
    if request.method == "POST":
        form = password_reset_form(request.POST)
        if form.is_valid():
            opts = {
                'use_https': request.is_secure(),
                'token_generator': token_generator,
                'from_email': from_email,
                'email_template_name': email_template_name,
                'subject_template_name': subject_template_name,
                'request': request,
            }
            if is_admin_site:
                opts = dict(opts, domain_override=request.get_host())
            form.save(**opts)
            return HttpResponseRedirect(post_reset_redirect)
    else:
        form = password_reset_form()
    context = {
        'form': form,
    }
    if extra_context is not None:
        context.update(extra_context)
    return TemplateResponse(request, template_name, context,
                            current_app=current_app)

      

Should I create a database table to store all previous user passwords or is there a django library that will provide me with this functionality.

+3


source to share


1 answer


Yes, you can create a model and keep all user passwords whenever the password is reset / changed.

from django.contrib.auth.models import User
import json

class OldPasswords(models.Model):
    user = model.ForeignKey(User)
    pwd = models.CharField(max_length=200)

    def setPasswords(self, pwd):
        self.pwd = json.dumps(pwd)

    def getPasswords(self):
        return json.loads(self.pwd)

      

create an alarm on password reset / change and save the current password.

eg:

from allauth.account.signals import password_changed, password_reset
def send_password_changed_email(sender, **kwargs):
    user = kwargs.get('user')
    if user:
       pwds = OldPasswords.objects.get_or_create(user=user)
       pwds.setPasswords(pwd)

      

Once saved in the model, you need to implement a custom validator to show a validation message when the user tries to use the old password, and reset:



  • validate (self, password, user = None): validate the password. Return None if the password is valid, or raise a ValidationError with if the password is not valid. You should be able to deal with the "No" user - if that means your validator is not working, just return None for no error.

  • get_help_text (): Provide help text to explain user requirements.

Any items in OPTIONS in AUTH_PASSWORD_VALIDATORS for your validator will be passed to the constructor. All constructor arguments must have a default value.

Here's a basic example of a validator with one additional setting:

from django.core.exceptions import ValidationError
from yourapp.model import OldPasswords 
from django.utils.translation import ugettext as _

class PasswordValidator(object):
    def __init__(self, password):
        self.password = password

    def validate(self, password, user=None):
        pwd_list = OldPasswords.objects.get(user=user).getPasswords() 
        if password in pwd_list:
            raise ValidationError(
                _("You used this password recently. Please choose a different one."),
                code='password_recently_used',
                params={'min_length': self.min_length},
            )

    def get_help_text(self):
        return _(
            "You used this password recently. Please choose a different one."
        )

      

However, if you choose to keep previous user passwords, you should never do so in clear text.

+2


source







All Articles