mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
[1.5.x] Fixed #19498 -- refactored auth documentation
The auth doc was a single page which had grown unwieldy. This refactor split and grouped the content into sub-topics. Additional corrections and cleanups were made along the way.
This commit is contained in:
2690
docs/topics/auth.txt
2690
docs/topics/auth.txt
File diff suppressed because it is too large
Load Diff
1068
docs/topics/auth/customizing.txt
Normal file
1068
docs/topics/auth/customizing.txt
Normal file
File diff suppressed because it is too large
Load Diff
1077
docs/topics/auth/default.txt
Normal file
1077
docs/topics/auth/default.txt
Normal file
File diff suppressed because it is too large
Load Diff
81
docs/topics/auth/index.txt
Normal file
81
docs/topics/auth/index.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
=============================
|
||||
User authentication in Django
|
||||
=============================
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
default
|
||||
passwords
|
||||
customizing
|
||||
|
||||
.. module:: django.contrib.auth
|
||||
:synopsis: Django's authentication framework.
|
||||
|
||||
Django comes with an user authentication system. It handles user accounts,
|
||||
groups, permissions and cookie-based user sessions. This section of the
|
||||
documentation explains how the default implementation works out of the box, as
|
||||
well as how to :doc:`extend and customize </topics/auth/customizing>` it to
|
||||
suit your project's needs.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The Django authentication system handles both authentication and authorization.
|
||||
Briefly, authentication verifies a user is who they claim to be, and
|
||||
authorization determines what an authenticated user is allowed to do. Here the
|
||||
term authentication is used to refer to both tasks.
|
||||
|
||||
The auth system consists of:
|
||||
|
||||
* Users
|
||||
* Permissions: Binary (yes/no) flags designating whether a user may perform
|
||||
a certain task.
|
||||
* Groups: A generic way of applying labels and permissions to more than one
|
||||
user.
|
||||
* A configurable password hashing system
|
||||
* Forms and view tools for logging in users, or restricting content
|
||||
* A pluggable backend system
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Authentication support is bundled as a Django contrib module in
|
||||
``django.contrib.auth``. By default, the required configuration is already
|
||||
included in the :file:`settings.py` generated by :djadmin:`django-admin.py
|
||||
startproject <startproject>`, these consist of two items listed in your
|
||||
:setting:`INSTALLED_APPS` setting:
|
||||
|
||||
1. ``'django.contrib.auth'`` contains the core of the authentication framework,
|
||||
and its default models.
|
||||
2. ``'django.contrib.contenttypes'`` is the Django :doc:`content type system
|
||||
</ref/contrib/contenttypes>`, which allows permissions to be associated with
|
||||
models you create.
|
||||
|
||||
and two items in your :setting:`MIDDLEWARE_CLASSES` setting:
|
||||
|
||||
1. :class:`~django.contrib.sessions.middleware.SessionMiddleware` manages
|
||||
:doc:`sessions </topics/http/sessions>` across requests.
|
||||
2. :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` associates
|
||||
users with requests using sessions.
|
||||
|
||||
With these settings in place, running the command ``manage.py syncdb`` creates
|
||||
the necessary database tables for auth related models, creates permissions for
|
||||
any models defined in your installed apps, and prompts you to create
|
||||
a superuser account the first time you run it.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
:doc:`Using Django's default implementation <default>`
|
||||
|
||||
* :ref:`Working with User objects <user-objects>`
|
||||
* :ref:`Permissions and authorization <topic-authorization>`
|
||||
* :ref:`Authentication in web requests <auth-web-requests>`
|
||||
* :ref:`Managing users in the admin <auth-admin>`
|
||||
|
||||
:doc:`API reference for the default implementation </ref/contrib/auth>`
|
||||
|
||||
:doc:`Customizing Users and authentication <customizing>`
|
||||
|
||||
:doc:`Password management in Django <passwords>`
|
||||
212
docs/topics/auth/passwords.txt
Normal file
212
docs/topics/auth/passwords.txt
Normal file
@@ -0,0 +1,212 @@
|
||||
=============================
|
||||
Password management in Django
|
||||
=============================
|
||||
|
||||
Password management is something that should generally not be reinvented
|
||||
unnecessarily, and Django endeavors to provide a secure and flexible set of
|
||||
tools for managing user passwords. This document describes how Django stores
|
||||
passwords, how the storage hashing can be configured, and some utilities to
|
||||
work with hashed passwords.
|
||||
|
||||
.. _auth_password_storage:
|
||||
|
||||
How Django stores passwords
|
||||
===========================
|
||||
|
||||
.. versionadded:: 1.4
|
||||
Django 1.4 introduces a new flexible password storage system and uses
|
||||
PBKDF2 by default. Previous versions of Django used SHA1, and other
|
||||
algorithms couldn't be chosen.
|
||||
|
||||
The :attr:`~django.contrib.auth.models.User.password` attribute of a
|
||||
:class:`~django.contrib.auth.models.User` object is a string in this format::
|
||||
|
||||
algorithm$hash
|
||||
|
||||
That's a storage algorithm, and hash, separated by the dollar-sign
|
||||
character. The algorithm is one of a number of one way hashing or password
|
||||
storage algorithms Django can use; see below. The hash is the result of the one-
|
||||
way function.
|
||||
|
||||
By default, Django uses the PBKDF2_ algorithm with a SHA256 hash, a
|
||||
password stretching mechanism recommended by NIST_. This should be
|
||||
sufficient for most users: it's quite secure, requiring massive
|
||||
amounts of computing time to break.
|
||||
|
||||
However, depending on your requirements, you may choose a different
|
||||
algorithm, or even use a custom algorithm to match your specific
|
||||
security situation. Again, most users shouldn't need to do this -- if
|
||||
you're not sure, you probably don't. If you do, please read on:
|
||||
|
||||
Django chooses the an algorithm by consulting the :setting:`PASSWORD_HASHERS`
|
||||
setting. This is a list of hashing algorithm classes that this Django
|
||||
installation supports. The first entry in this list (that is,
|
||||
``settings.PASSWORD_HASHERS[0]``) will be used to store passwords, and all the
|
||||
other entries are valid hashers that can be used to check existing passwords.
|
||||
This means that if you want to use a different algorithm, you'll need to modify
|
||||
:setting:`PASSWORD_HASHERS` to list your preferred algorithm first in the list.
|
||||
|
||||
The default for :setting:`PASSWORD_HASHERS` is::
|
||||
|
||||
PASSWORD_HASHERS = (
|
||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
||||
'django.contrib.auth.hashers.SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||
'django.contrib.auth.hashers.CryptPasswordHasher',
|
||||
)
|
||||
|
||||
This means that Django will use PBKDF2_ to store all passwords, but will support
|
||||
checking passwords stored with PBKDF2SHA1, bcrypt_, SHA1_, etc. The next few
|
||||
sections describe a couple of common ways advanced users may want to modify this
|
||||
setting.
|
||||
|
||||
.. _bcrypt_usage:
|
||||
|
||||
Using bcrypt with Django
|
||||
------------------------
|
||||
|
||||
Bcrypt_ is a popular password storage algorithm that's specifically designed
|
||||
for long-term password storage. It's not the default used by Django since it
|
||||
requires the use of third-party libraries, but since many people may want to
|
||||
use it Django supports bcrypt with minimal effort.
|
||||
|
||||
To use Bcrypt as your default storage algorithm, do the following:
|
||||
|
||||
1. Install the `py-bcrypt`_ library (probably by running ``sudo pip install
|
||||
py-bcrypt``, or downloading the library and installing it with ``python
|
||||
setup.py install``).
|
||||
|
||||
2. Modify :setting:`PASSWORD_HASHERS` to list ``BCryptPasswordHasher``
|
||||
first. That is, in your settings file, you'd put::
|
||||
|
||||
PASSWORD_HASHERS = (
|
||||
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||
'django.contrib.auth.hashers.CryptPasswordHasher',
|
||||
)
|
||||
|
||||
(You need to keep the other entries in this list, or else Django won't
|
||||
be able to upgrade passwords; see below).
|
||||
|
||||
That's it -- now your Django install will use Bcrypt as the default storage
|
||||
algorithm.
|
||||
|
||||
.. admonition:: Other bcrypt implementations
|
||||
|
||||
There are several other implementations that allow bcrypt to be
|
||||
used with Django. Django's bcrypt support is NOT directly
|
||||
compatible with these. To upgrade, you will need to modify the
|
||||
hashes in your database to be in the form `bcrypt$(raw bcrypt
|
||||
output)`. For example:
|
||||
`bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy`.
|
||||
|
||||
Increasing the work factor
|
||||
--------------------------
|
||||
|
||||
The PBKDF2 and bcrypt algorithms use a number of iterations or rounds of
|
||||
hashing. This deliberately slows down attackers, making attacks against hashed
|
||||
passwords harder. However, as computing power increases, the number of
|
||||
iterations needs to be increased. We've chosen a reasonable default (and will
|
||||
increase it with each release of Django), but you may wish to tune it up or
|
||||
down, depending on your security needs and available processing power. To do so,
|
||||
you'll subclass the appropriate algorithm and override the ``iterations``
|
||||
parameters. For example, to increase the number of iterations used by the
|
||||
default PBKDF2 algorithm:
|
||||
|
||||
1. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``::
|
||||
|
||||
from django.contrib.auth.hashers import PBKDF2PasswordHasher
|
||||
|
||||
class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
|
||||
"""
|
||||
A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.
|
||||
"""
|
||||
iterations = PBKDF2PasswordHasher.iterations * 100
|
||||
|
||||
Save this somewhere in your project. For example, you might put this in
|
||||
a file like ``myproject/hashers.py``.
|
||||
|
||||
2. Add your new hasher as the first entry in :setting:`PASSWORD_HASHERS`::
|
||||
|
||||
PASSWORD_HASHERS = (
|
||||
'myproject.hashers.MyPBKDF2PasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
||||
'django.contrib.auth.hashers.SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||
'django.contrib.auth.hashers.CryptPasswordHasher',
|
||||
)
|
||||
|
||||
|
||||
That's it -- now your Django install will use more iterations when it
|
||||
stores passwords using PBKDF2.
|
||||
|
||||
Password upgrading
|
||||
------------------
|
||||
|
||||
When users log in, if their passwords are stored with anything other than
|
||||
the preferred algorithm, Django will automatically upgrade the algorithm
|
||||
to the preferred one. This means that old installs of Django will get
|
||||
automatically more secure as users log in, and it also means that you
|
||||
can switch to new (and better) storage algorithms as they get invented.
|
||||
|
||||
However, Django can only upgrade passwords that use algorithms mentioned in
|
||||
:setting:`PASSWORD_HASHERS`, so as you upgrade to new systems you should make
|
||||
sure never to *remove* entries from this list. If you do, users using un-
|
||||
mentioned algorithms won't be able to upgrade.
|
||||
|
||||
.. _sha1: http://en.wikipedia.org/wiki/SHA1
|
||||
.. _pbkdf2: http://en.wikipedia.org/wiki/PBKDF2
|
||||
.. _nist: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
|
||||
.. _bcrypt: http://en.wikipedia.org/wiki/Bcrypt
|
||||
.. _py-bcrypt: http://pypi.python.org/pypi/py-bcrypt/
|
||||
|
||||
|
||||
Manually managing a user's password
|
||||
===================================
|
||||
|
||||
.. module:: django.contrib.auth.hashers
|
||||
|
||||
.. versionadded:: 1.4
|
||||
The :mod:`django.contrib.auth.hashers` module provides a set of functions
|
||||
to create and validate hashed password. You can use them independently
|
||||
from the ``User`` model.
|
||||
|
||||
.. function:: check_password(password, encoded)
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
If you'd like to manually authenticate a user by comparing a plain-text
|
||||
password to the hashed password in the database, use the convenience
|
||||
function :func:`django.contrib.auth.hashers.check_password`. It takes two
|
||||
arguments: the plain-text password to check, and the full value of a
|
||||
user's ``password`` field in the database to check against, and returns
|
||||
``True`` if they match, ``False`` otherwise.
|
||||
|
||||
.. function:: make_password(password[, salt, hashers])
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
Creates a hashed password in the format used by this application. It takes
|
||||
one mandatory argument: the password in plain-text. Optionally, you can
|
||||
provide a salt and a hashing algorithm to use, if you don't want to use the
|
||||
defaults (first entry of ``PASSWORD_HASHERS`` setting).
|
||||
Currently supported algorithms are: ``'pbkdf2_sha256'``, ``'pbkdf2_sha1'``,
|
||||
``'bcrypt'`` (see :ref:`bcrypt_usage`), ``'sha1'``, ``'md5'``,
|
||||
``'unsalted_md5'`` (only for backward compatibility) and ``'crypt'``
|
||||
if you have the ``crypt`` library installed. If the password argument is
|
||||
``None``, an unusable password is returned (a one that will be never
|
||||
accepted by :func:`django.contrib.auth.hashers.check_password`).
|
||||
|
||||
.. function:: is_password_usable(encoded_password)
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
Checks if the given string is a hashed password that has a chance
|
||||
of being verified against :func:`django.contrib.auth.hashers.check_password`.
|
||||
@@ -1063,52 +1063,46 @@ Proxy models are declared like normal models. You tell Django that it's a
|
||||
proxy model by setting the :attr:`~django.db.models.Options.proxy` attribute of
|
||||
the ``Meta`` class to ``True``.
|
||||
|
||||
For example, suppose you want to add a method to the standard
|
||||
:class:`~django.contrib.auth.models.User` model that will be used in your
|
||||
templates. You can do it like this::
|
||||
For example, suppose you want to add a method to the ``Person`` model described
|
||||
above. You can do it like this::
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class MyUser(User):
|
||||
class MyPerson(Person):
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
def do_something(self):
|
||||
...
|
||||
|
||||
The ``MyUser`` class operates on the same database table as its parent
|
||||
:class:`~django.contrib.auth.models.User` class. In particular, any new
|
||||
instances of :class:`~django.contrib.auth.models.User` will also be accessible
|
||||
through ``MyUser``, and vice-versa::
|
||||
The ``MyPerson`` class operates on the same database table as its parent
|
||||
``Person`` class. In particular, any new instances of ``Person`` will also be
|
||||
accessible through ``MyPerson``, and vice-versa::
|
||||
|
||||
>>> u = User.objects.create(username="foobar")
|
||||
>>> MyUser.objects.get(username="foobar")
|
||||
<MyUser: foobar>
|
||||
>>> p = Person.objects.create(first_name="foobar")
|
||||
>>> MyPerson.objects.get(first_name="foobar")
|
||||
<MyPerson: foobar>
|
||||
|
||||
You could also use a proxy model to define a different default ordering on a
|
||||
model. The standard :class:`~django.contrib.auth.models.User` model has no
|
||||
ordering defined on it (intentionally; sorting is expensive and we don't want
|
||||
to do it all the time when we fetch users). You might want to regularly order
|
||||
by the ``username`` attribute when you use the proxy. This is easy::
|
||||
You could also use a proxy model to define a different default ordering on
|
||||
a model. You might not always want to order the ``Person`` model, but regularly
|
||||
order by the ``last_name`` attribute when you use the proxy. This is easy::
|
||||
|
||||
class OrderedUser(User):
|
||||
class OrderedPerson(Person):
|
||||
class Meta:
|
||||
ordering = ["username"]
|
||||
ordering = ["last_name"]
|
||||
proxy = True
|
||||
|
||||
Now normal :class:`~django.contrib.auth.models.User` queries will be unordered
|
||||
and ``OrderedUser`` queries will be ordered by ``username``.
|
||||
Now normal ``Person`` queries will be unordered
|
||||
and ``OrderedPerson`` queries will be ordered by ``last_name``.
|
||||
|
||||
QuerySets still return the model that was requested
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There is no way to have Django return, say, a ``MyUser`` object whenever you
|
||||
query for :class:`~django.contrib.auth.models.User` objects. A queryset for
|
||||
``User`` objects will return those types of objects. The whole point of proxy
|
||||
objects is that code relying on the original ``User`` will use those and your
|
||||
own code can use the extensions you included (that no other code is relying on
|
||||
anyway). It is not a way to replace the ``User`` (or any other) model
|
||||
everywhere with something of your own creation.
|
||||
There is no way to have Django return, say, a ``MyPerson`` object whenever you
|
||||
query for ``Person`` objects. A queryset for ``Person`` objects will return
|
||||
those types of objects. The whole point of proxy objects is that code relying
|
||||
on the original ``Person`` will use those and your own code can use the
|
||||
extensions you included (that no other code is relying on anyway). It is not
|
||||
a way to replace the ``Person`` (or any other) model everywhere with something
|
||||
of your own creation.
|
||||
|
||||
Base class restrictions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -1131,12 +1125,12 @@ it will become the default, although any managers defined on the parent
|
||||
classes will still be available.
|
||||
|
||||
Continuing our example from above, you could change the default manager used
|
||||
when you query the ``User`` model like this::
|
||||
when you query the ``Person`` model like this::
|
||||
|
||||
class NewManager(models.Manager):
|
||||
...
|
||||
|
||||
class MyUser(User):
|
||||
class MyPerson(Person):
|
||||
objects = NewManager()
|
||||
|
||||
class Meta:
|
||||
@@ -1154,7 +1148,7 @@ containing the new managers and inherit that after the primary base class::
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
class MyUser(User, ExtraManagers):
|
||||
class MyPerson(Person, ExtraManagers):
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Introductions to all the key parts of Django you'll need to know:
|
||||
class-based-views/index
|
||||
files
|
||||
testing/index
|
||||
auth
|
||||
auth/index
|
||||
cache
|
||||
conditional-view-processing
|
||||
signing
|
||||
|
||||
@@ -651,7 +651,7 @@ Use the ``django.test.client.Client`` class to make requests.
|
||||
|
||||
.. method:: Client.login(**credentials)
|
||||
|
||||
If your site uses Django's :doc:`authentication system</topics/auth>`
|
||||
If your site uses Django's :doc:`authentication system</topics/auth/index>`
|
||||
and you deal with logging in users, you can use the test client's
|
||||
``login()`` method to simulate the effect of a user logging into the
|
||||
site.
|
||||
@@ -695,7 +695,7 @@ Use the ``django.test.client.Client`` class to make requests.
|
||||
|
||||
.. method:: Client.logout()
|
||||
|
||||
If your site uses Django's :doc:`authentication system</topics/auth>`,
|
||||
If your site uses Django's :doc:`authentication system</topics/auth/index>`,
|
||||
the ``logout()`` method can be used to simulate the effect of a user
|
||||
logging out of your site.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user