kokobob.com

Enhancing Django's Password Validators with Custom Solutions

Written on

Welcome to Django Shorts

Django comes equipped with a decent array of password validators by default, but you might want to create your own. Fortunately, this process is straightforward!

In this tutorial series, we aim to provide quick and effective solutions tailored to various requirements within your Django projects, while enhancing your expertise.

Django is designed for perfectionists working against deadlines, so let’s refine our password validators.

Prerequisites This article assumes you have prior experience with Django projects.

Understanding Password Validators

Password validators are snippets of code that verify whether a password fulfills specific criteria. Their primary purpose is to ensure that passwords are not mere sequences of characters easily subjected to brute-force or dictionary attacks.

Common rules for password validation include: - At least one digit - At least one uppercase letter - At least one lowercase letter - At least one special character

Built-in Password Validators in Django

Django includes a range of built-in password validators that enforce the following rules: - Password similarity to the username - Minimum password length - Passwords that match commonly used passwords (20,000 records) - Passwords that are entirely numeric

To utilize these validators, you must specify them in the settings.py file:

AUTH_PASSWORD_VALIDATORS = [

{

'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',

},

{

'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',

'OPTIONS': {

'min_length': 9,

}

},

{

'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',

},

{

'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',

},

]

Some validators allow configuration options; for instance, the minimum length validator specifies a password length (default is 8 characters).

Error messages and guidance text are presented to the user in the order defined in the settings.

Creating Simple Custom Password Validators

Developing a custom password validator for Django is quite simple. You just need to create a class that implements two methods: - validate: This method checks the password against the specified rules and either returns None (indicating success) or raises a ValidationError (if validation fails). - get_help_text: This method returns the guidance text displayed to the user.

Here’s an example of a custom validator that checks for at least one digit (using regex):

class NumberValidator(object):

def validate(self, password, user=None):

if not re.findall(r'd', password):

raise ValidationError(

_("The password must contain at least 1 digit, 0-9."),

code='password_no_number',

)

def get_help_text(self):

return _("Your password must contain at least 1 digit, 0-9.")

You can create additional custom validators by following this pattern. Let’s examine a complete example of custom validators, which we will place in a separate file named validators.py.

Walkthrough of the Custom Validators Code - Line 6 defines a NumberValidator that checks for at least one digit. - Line 20 introduces an UppercaseValidator that ensures the password contains at least one uppercase letter. - Line 34 adds a SymbolValidator that validates for at least one special character.

Each validator implements a straightforward regex rule to check and validate the specified criteria.

To use your new custom validators, they must be added to the settings.py file:

AUTH_PASSWORD_VALIDATORS = [

{

'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',

},

{

'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',

'OPTIONS': {

'min_length': 9,

}

},

{

'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',

},

{

'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',

},

{

'NAME': 'password_validators.validators.NumberValidator',

},

{

'NAME': 'password_validators.validators.UppercaseValidator',

},

{

'NAME': 'password_validators.validators.SymbolValidator',

},

]

Let’s see these validators in action.

You can log into the Django Admin dashboard and attempt to change a user's password using the standard form.

Accessing Model Data with Custom Password Validators A common requirement for password validation is checking if a new password is identical to any that the user has previously used. This requires accessing stored data, necessitating a model definition to read and write hashed passwords securely.

Let’s begin by defining our StoredPassword model in models.py:

from django.conf import settings

from django.db import models

class StoredPassword(models.Model):

user = models.ForeignKey(

settings.AUTH_USER_MODEL,

on_delete=models.CASCADE,

editable=False

)

password = models.CharField(

'Password hash',

max_length=255,

editable=False

)

date = models.DateTimeField(

'Date',

auto_now_add=True,

editable=False

)

This model definition is quite simple, storing the user, hashed password, and the creation date for reference.

Since we now have a model, we must ensure that the application defining the model is included in the settings.py file:

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'password_validators',

]

Also, remember to create and run the database migrations:

$ python3 manage.py makemigrations

$ python3 manage.py migrate

With the model in place to store previous passwords, we can now add the new custom password validator:

Code Walkthrough - Line 7 defines the SALT used to hash the password stored in our model. - Line 53 implements the repeated password validator, which includes defining the validate method and the password_changed method (triggered after a successful password change) to store the passwords. - Lines 59-61 hash the password using the SALT and check if an identical record (user/password combination) exists in the database. - Lines 72-78 hash the password and verify if the record already exists in the database (which it shouldn't) and then store it in the StoredPassword model.

If you attempt to change the password to a previously used one, you will see the following error:

Note that you must change the password twice to ensure a prior password matches the rule.

Conclusion

As demonstrated, implementing password validators in Django is quite simple and allows for customization of password validation rules, which is essential for compliance with certain regulations.

Explore the complete source code on GitHub at: https://github.com/nunombispo/DjangoShorts-PasswordValidators

Discover more Python/Django shorts:

  • Python Shorts — NLP Sentiment Analysis and Text Summary

    What if you could perform sentiment analysis and create text summaries using Python and NLP without relying on costly APIs?

  • Django Shorts — User Authentication and Lockout

    Django already offers robust user security, but what if you want to implement account lockout?

Follow me on Twitter: https://twitter.com/DevAsService Visit my website: https://developer-service.io/

If you enjoyed this article and found it helpful, consider supporting me by signing up for a Medium membership (if you aren’t a member yet). It costs just $5 a month and grants you access to all stories on Medium! (I will receive a small commission).

To stay updated on my latest posts, feel free to sign up for my free newsletter!

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Staying Motivated: Simple Strategies for Everyday Inspiration

Discover effective strategies to maintain motivation daily through positive habits and supportive relationships.

Exploring Nature's Most Fascinating Optical Illusions

Discover seven captivating optical illusions found in nature, showcasing the extraordinary interplay of light and environmental conditions.

Effortlessly Manage Your Gmail: Automate Email Deletion

Discover how to automatically delete old emails in Gmail, reducing clutter effortlessly with a simple script.

Overcoming Fear: Steps to Take Action and Embrace Growth

Discover how to conquer fear and inaction to lead a fulfilling life. Learn actionable steps to embrace growth and self-improvement.

Innovative Army Vaccine Aims to Combat All Covid Variants

The Army's new vaccine could end the pandemic by targeting all Covid variants, including Omicron and SARS.

Transforming Business Ethics: Beyond

Exploring the moral implications of business practices and advocating for a more compassionate approach to entrepreneurship.

# Discovering the Benefits of Oranges: Nature's Nutritional Powerhouse

Explore the remarkable health benefits of oranges, from immune support to heart health, and learn why they are a kitchen staple.

Understanding the Allure of Conspiracy Theories in Society

This article explores the psychology behind belief in conspiracy theories and how pattern recognition plays a role in this phenomenon.