From 1daae25bdcd735151de394a5578c22257e3e5dc7 Mon Sep 17 00:00:00 2001 From: Erik Romijn Date: Sun, 8 Mar 2015 15:07:57 +0100 Subject: Fixed #16860 -- Added password validation to django.contrib.auth. --- docs/ref/settings.txt | 13 +++ docs/releases/1.9.txt | 40 +++++++- docs/topics/auth/passwords.txt | 214 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index c745ad519b..a0c3e69877 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -2767,6 +2767,19 @@ Default:: 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher', 'django.contrib.auth.hashers.CryptPasswordHasher'] +.. setting:: AUTH_PASSWORD_VALIDATORS + +AUTH_PASSWORD_VALIDATORS +------------------------ + +.. versionadded:: 1.9 + +Default: ``[]`` + +Sets the validators that are used to check the strength of user's passwords. +See :ref:`password-validation` for more details. +By default, no validation is performed and all passwords are accepted. + .. _settings-messages: Messages diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index afa624e295..ffa17391ec 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -25,7 +25,45 @@ Python 3.2 and added support for Python 3.5. What's new in Django 1.9 ======================== -... +Password validation +~~~~~~~~~~~~~~~~~~~ + +Django now offers password validation, to help prevent the usage of weak +passwords by users. The validation is integrated in the included password +change and reset forms and is simple to integrate in any other code. +Validation is performed by one or more validators, configured in the new +:setting:`AUTH_PASSWORD_VALIDATORS` setting. + +Four validators are included in Django, which can enforce a minimum length, +compare the password to the user's attributes like their name, ensure +passwords aren't entirely numeric or check against an included list of common +passwords. You can combine multiple validators, and some validators have +custom configuration options. For example, you can choose to provide a custom +list of common passwords. Each validator provides a help text to explain their +requirements to the user. + +By default, no validation is performed and all passwords are accepted, so if +you don't set :setting:`AUTH_PASSWORD_VALIDATORS`, you will not see any +change. In new projects created with the default :djadmin:`startproject` +template, a simple set of validators is enabled. To enable basic validation in +the included auth forms for your project, you could set, for example:: + + AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, + ] + +See :ref:`password-validation` for more details. Minor features ~~~~~~~~~~~~~~ diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt index 5f7bece6ee..090c9196b6 100644 --- a/docs/topics/auth/passwords.txt +++ b/docs/topics/auth/passwords.txt @@ -236,3 +236,217 @@ from the ``User`` model. Checks if the given string is a hashed password that has a chance of being verified against :func:`check_password`. + +.. _password-validation: + +Password validation +=================== + +Users often choose poor passwords. To help mitigate this problem, Django +offers pluggable password validation. You can configure multiple password +validators at the same time. A few validators are included in Django, but it's +simple to write your own as well. + +Each password validator must provide a help text to explain the requirements to +the user, validate a given password and return an error message if it does not +meet the requirements, and optionally receive passwords that have been set. +Validators can also have optional settings to fine tune their behavior. + +Validation is controlled by the :setting:`AUTH_PASSWORD_VALIDATORS` setting. +By default, validators are used in the forms to reset or change passwords. +The default for setting is an empty list, which means no validators are +applied. In new projects created with the default :djadmin:`startproject` +template, a simple set of validators is enabled. + +.. note:: + + Password validation can prevent the use of many types of weak passwords. + However, the fact that a password passes all the validators, doesn't + guarantee that it is a strong password. There are many factors that can + weaken a password that are not detectable by even the most advanced + password validators. + +Enabling password validation +---------------------------- + +Password validation is configured in the +:setting:`AUTH_PASSWORD_VALIDATORS` setting:: + + 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', + }, + ] + +This example enables all four included validators: + +* ``UserAttributeSimilarityValidator``, which checks the similarity between + the password and a set of attributes of the user. +* ``MinimumLengthValidator``, which simply checks whether the password meets a + minimum length. This validator is configured with a custom option: it now + requires the minimum length to be nine characters, instead of the default + eight. +* ``CommonPasswordValidator``, which checks whether the password occurs in a + list of common passwords. By default, it compares to an included list of + 1000 common passwords. +* ``NumericPasswordValidator``, which checks whether the password isn't + entirely numeric. + +For ``UserAttributeSimilarityValidator`` and ``CommonPasswordValidator``, +we're simply using the default settings in this example. +``NumericPasswordValidator`` has no settings. + +The help texts and any errors from password validators are always returned in +the order they are listed in :setting:`AUTH_PASSWORD_VALIDATORS`. + +Included validators +------------------- + +Django includes four validators: + +.. class:: MinimumLengthValidator(min_length=8) + + Validates whether the password meets a minimum length. + The minimum length can be customized with the ``min_length`` parameter. + +.. class:: UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7) + + Validates whether the password is sufficiently different from certain + attributes of the user. + + The ``user_attributes`` parameter should be an iterable of names of user + attributes to compare to. If this argument is not provided, the default + is used: ``'username', 'first_name', 'last_name', 'email'``. + Attributes that don't exist are ignored. + + The maximum similarity the password can have, before it is rejected, can + be set with the ``max_similarity`` parameter, on a scale of 0 to 1. + A setting of 0 will cause all passwords to be rejected, whereas a setting + of 1 will cause it to only reject passwords that are identical to an + attribute's value. + +.. class:: CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH) + + Validates whether the password is not a common password. By default, this + checks against a list of 1000 common password created by + `Mark Burnett `_. + + The ``password_list_path`` can be set to the path of a custom file of + common passwords. This file should contain one password per line, and + may be plain text or gzipped. + +.. class:: NumericPasswordValidator() + + Validates whether the password is not entirely numeric. + +Integrating validation +----------------------- + +.. module:: django.contrib.auth.password_validation + +There are a few functions in ``django.contrib.auth.password_validation`` that +you can call from your own forms or other code to integrate password +validation. This can be useful if you use custom forms for password setting, +or if you have API calls that allow passwords to be set, for example. + +.. function:: validate_password(password, user=None, password_validators=None) + + Validates a password. If all validators find the password valid, returns + ``None``. If one or more validators reject the password, raises a + :exc:`~django.core.exceptions.ValidationError` with all the error messages + from the validators. + + The user object is optional: if it's not provided, some validators may not + be able to perform any validation and will accept any password. + +.. function:: password_changed(password, user=None, password_validators=None) + + Informs all validators that the password has been changed. This can be used + by some validators, e.g. a validator that prevents password reuse. This + should be called once the password has been successfully changed. + +.. function:: password_validators_help_texts(password_validators=None) + + Returns a list of the help texts of all validators. These explain the + password requirements to the user. + +.. function:: password_validators_help_text_html(password_validators=None) + + Returns an HTML string with all help texts in an ``