You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1339 lines
49 KiB
1339 lines
49 KiB
.. _topics-auth: |
|
|
|
============================= |
|
User authentication in Django |
|
============================= |
|
|
|
.. module:: django.contrib.auth |
|
:synopsis: Django's authentication framework. |
|
|
|
Django comes with a user authentication system. It handles user accounts, |
|
groups, permissions and cookie-based user sessions. This document explains how |
|
things work. |
|
|
|
Overview |
|
======== |
|
|
|
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. |
|
* Messages: A simple way to queue messages for given users. |
|
|
|
Installation |
|
============ |
|
|
|
Authentication support is bundled as a Django application in |
|
``django.contrib.auth``. To install it, do the following: |
|
|
|
1. Put ``'django.contrib.auth'`` in your :setting:`INSTALLED_APPS` setting. |
|
2. Run the command ``manage.py syncdb``. |
|
|
|
Note that the default :file:`settings.py` file created by |
|
:djadmin:`django-admin.py startproject` includes ``'django.contrib.auth'`` in |
|
:setting:`INSTALLED_APPS` for convenience. If your :setting:`INSTALLED_APPS` |
|
already contains ``'django.contrib.auth'``, feel free to run |
|
:djadmin:`manage.py syncdb` again; you can run that command as many times as |
|
you'd like, and each time it'll only install what's needed. |
|
|
|
The :djadmin:`syncdb` command creates the necessary database tables, creates |
|
permission objects for all installed apps that need 'em, and prompts you to |
|
create a superuser account the first time you run it. |
|
|
|
Once you've taken those steps, that's it. |
|
|
|
Users |
|
===== |
|
|
|
.. class:: models.User |
|
|
|
API reference |
|
------------- |
|
|
|
Fields |
|
~~~~~~ |
|
|
|
.. class:: models.User |
|
|
|
:class:`~django.contrib.auth.models.User` objects have the following fields: |
|
|
|
.. attribute:: models.User.username |
|
|
|
Required. 30 characters or fewer. Alphanumeric characters only (letters, |
|
digits and underscores). |
|
|
|
.. attribute:: models.User.first_name |
|
|
|
Optional. 30 characters or fewer. |
|
|
|
.. attribute:: models.User.last_name |
|
|
|
Optional. 30 characters or fewer. |
|
|
|
.. attribute:: models.User.email |
|
|
|
Optional. E-mail address. |
|
|
|
.. attribute:: models.User.password |
|
|
|
Required. A hash of, and metadata about, the password. (Django doesn't |
|
store the raw password.) Raw passwords can be arbitrarily long and can |
|
contain any character. See the "Passwords" section below. |
|
|
|
.. attribute:: models.User.is_staff |
|
|
|
Boolean. Designates whether this user can access the admin site. |
|
|
|
.. attribute:: models.User.is_active |
|
|
|
Boolean. Designates whether this account can be used to log in. Set this |
|
flag to ``False`` instead of deleting accounts. |
|
|
|
.. attribute:: models.User.is_superuser |
|
|
|
Boolean. Designates that this user has all permissions without explicitly |
|
assigning them. |
|
|
|
.. attribute:: models.User.last_login |
|
|
|
A datetime of the user's last login. Is set to the current date/time by |
|
default. |
|
|
|
.. attribute:: models.User.date_joined |
|
|
|
A datetime designating when the account was created. Is set to the current |
|
date/time by default when the account is created. |
|
|
|
Methods |
|
~~~~~~~ |
|
|
|
.. class:: models.User |
|
|
|
:class:`~django.contrib.auth.models.User` objects have two many-to-many |
|
fields: models.User. ``groups`` and ``user_permissions``. |
|
:class:`~django.contrib.auth.models.User` objects can access their related |
|
objects in the same way as any other :ref:`Django model <topics-db-models>`: |
|
|
|
.. code-block:: python |
|
|
|
myuser.groups = [group_list] |
|
myuser.groups.add(group, group, ...) |
|
myuser.groups.remove(group, group, ...) |
|
myuser.groups.clear() |
|
myuser.user_permissions = [permission_list] |
|
myuser.user_permissions.add(permission, permission, ...) |
|
myuser.user_permissions.remove(permission, permission, ...) |
|
myuser.user_permissions.clear() |
|
|
|
In addition to those automatic API methods, |
|
:class:`~django.contrib.auth.models.User` objects have the following custom |
|
methods: |
|
|
|
.. method:: models.User.is_anonymous() |
|
|
|
Always returns ``False``. This is a way of differentiating |
|
:class:`~django.contrib.auth.models.User` and |
|
:class:`~django.contrib.auth.models.AnonymousUser` objects. |
|
Generally, you should prefer using |
|
:meth:`~django.contrib.auth.models.User.is_authenticated()` to this |
|
method. |
|
|
|
.. method:: models.User.is_authenticated() |
|
|
|
Always returns ``True``. This is a way to |
|
tell if the user has been authenticated. This does not imply any |
|
permissions, and doesn't check if the user is active - it only indicates |
|
that the user has provided a valid username and password. |
|
|
|
.. method:: models.User.get_full_name() |
|
|
|
Returns the :attr:`~django.contrib.auth.models.User.first_name` plus the |
|
:attr:`~django.contrib.auth.models.User.last_name`, |
|
with a space in between. |
|
|
|
.. method:: models.User.set_password(raw_password) |
|
|
|
Sets the user's password to the given raw string, taking care of the |
|
password hashing. Doesn't save the |
|
:class:`~django.contrib.auth.models.User` object. |
|
|
|
.. method:: models.User.check_password(raw_password) |
|
|
|
Returns ``True`` if the given raw string is the correct password for the |
|
user. (This takes care of the password hashing in making the comparison.) |
|
|
|
.. method:: models.User.set_unusable_password() |
|
|
|
.. versionadded:: 1.0 |
|
|
|
Marks the user as having no password set. This isn't the same as having |
|
a blank string for a password. |
|
:meth:`~django.contrib.auth.models.User.check_password()` for this user |
|
will never return ``True``. Doesn't save the |
|
:class:`~django.contrib.auth.models.User` object. |
|
|
|
You may need this if authentication for your application takes place |
|
against an existing external source such as an LDAP directory. |
|
|
|
.. method:: models.User.has_usable_password() |
|
|
|
.. versionadded:: 1.0 |
|
|
|
Returns ``False`` if |
|
:meth:`~django.contrib.auth.models.User.set_unusable_password()` has |
|
been called for this user. |
|
|
|
.. method:: models.User.get_group_permissions() |
|
|
|
Returns a list of permission strings that the user has, through his/her |
|
groups. |
|
|
|
.. method:: models.User.get_all_permissions() |
|
|
|
Returns a list of permission strings that the user has, both through group |
|
and user permissions. |
|
|
|
.. method:: models.User.has_perm(perm) |
|
|
|
Returns ``True`` if the user has the specified permission, where perm is |
|
in the format ``"package.codename"``. If the user is inactive, this method |
|
will always return ``False``. |
|
|
|
.. method:: models.User.has_perms(perm_list) |
|
|
|
Returns ``True`` if the user has each of the specified permissions, where |
|
each perm is in the format ``"package.codename"``. If the user is inactive, |
|
this method will always return ``False``. |
|
|
|
.. method:: models.User.has_module_perms(package_name) |
|
|
|
Returns ``True`` if the user has any permissions in the given package (the |
|
Django app label). If the user is inactive, this method will always return |
|
``False``. |
|
|
|
.. method:: models.User.get_and_delete_messages() |
|
|
|
Returns a list of :class:`~django.contrib.auth.models.Message` objects in |
|
the user's queue and deletes the messages from the queue. |
|
|
|
.. method:: models.User.email_user(subject, message, from_email=None) |
|
|
|
Sends an e-mail to the user. If |
|
:attr:`~django.contrib.auth.models.User.from_email` is ``None``, Django |
|
uses the :setting:`DEFAULT_FROM_EMAIL`. |
|
|
|
.. method:: models.User.get_profile() |
|
|
|
Returns a site-specific profile for this user. Raises |
|
:exc:`django.contrib.auth.models.SiteProfileNotAvailable` if the current |
|
site doesn't allow profiles. For information on how to define a |
|
site-specific user profile, see the section on |
|
`storing additional user information`_ below. |
|
|
|
.. _storing additional user information: #storing-additional-information-about-users |
|
|
|
Manager functions |
|
~~~~~~~~~~~~~~~~~ |
|
|
|
.. class:: models.UserManager |
|
|
|
The :class:`~django.contrib.auth.models.User` model has a custom manager |
|
that has the following helper functions: |
|
|
|
.. method:: models.UserManager.create_user(username, email, password=None) |
|
|
|
Creates, saves and returns a :class:`~django.contrib.auth.models.User`. |
|
The :attr:`~django.contrib.auth.models.User.username`, |
|
:attr:`~django.contrib.auth.models.User.email` and |
|
:attr:`~django.contrib.auth.models.User.password` are set as given, and the |
|
:class:`~django.contrib.auth.models.User` gets ``is_active=True``. |
|
|
|
If no password is provided, |
|
:meth:`~django.contrib.auth.models.User.set_unusable_password()` will be |
|
called. |
|
|
|
See `Creating users`_ for example usage. |
|
|
|
.. method:: models.UserManager.make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') |
|
|
|
Returns a random password with the given length and given string of |
|
allowed characters. (Note that the default value of ``allowed_chars`` |
|
doesn't contain letters that can cause user confusion, including ``1``, |
|
``I`` and ``0``). |
|
|
|
Basic usage |
|
----------- |
|
|
|
.. _topics-auth-creating-users: |
|
|
|
Creating users |
|
~~~~~~~~~~~~~~ |
|
|
|
The most basic way to create users is to use the |
|
:meth:`~django.contrib.auth.models.UserManager.create_user` helper function |
|
that comes with Django:: |
|
|
|
>>> from django.contrib.auth.models import User |
|
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') |
|
|
|
# At this point, user is a User object that has already been saved |
|
# to the database. You can continue to change its attributes |
|
# if you want to change other fields. |
|
>>> user.is_staff = True |
|
>>> user.save() |
|
|
|
Changing passwords |
|
~~~~~~~~~~~~~~~~~~ |
|
|
|
Change a password with :meth:`~django.contrib.auth.models.User.set_password()`:: |
|
|
|
>>> from django.contrib.auth.models import User |
|
>>> u = User.objects.get(username__exact='john') |
|
>>> u.set_password('new password') |
|
>>> u.save() |
|
|
|
Don't set the :attr:`~django.contrib.auth.models.User.password` attribute |
|
directly unless you know what you're doing. This is explained in the next |
|
section. |
|
|
|
Passwords |
|
--------- |
|
|
|
The :attr:`~django.contrib.auth.models.User.password` attribute of a |
|
:class:`~django.contrib.auth.models.User` object is a string in this format:: |
|
|
|
hashtype$salt$hash |
|
|
|
That's hashtype, salt and hash, separated by the dollar-sign character. |
|
|
|
Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm |
|
used to perform a one-way hash of the password. Salt is a random string used |
|
to salt the raw password to create the hash. Note that the ``crypt`` method is |
|
only supported on platforms that have the standard Python ``crypt`` module |
|
available, and ``crypt`` support is only available in the Django development |
|
version. |
|
|
|
For example:: |
|
|
|
sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 |
|
|
|
The :meth:`~django.contrib.auth.models.User.set_password` and |
|
:meth:`~django.contrib.auth.models.User.check_password` functions handle the |
|
setting and checking of these values behind the scenes. |
|
|
|
Previous Django versions, such as 0.90, used simple MD5 hashes without password |
|
salts. For backwards compatibility, those are still supported; they'll be |
|
converted automatically to the new style the first time |
|
:meth:`~django.contrib.auth.models.User.check_password()` works correctly for |
|
a given user. |
|
|
|
Anonymous users |
|
--------------- |
|
|
|
.. class:: models.AnonymousUser |
|
|
|
:class:`django.contrib.auth.models.AnonymousUser` is a class that |
|
implements the :class:`django.contrib.auth.models.User` interface, with |
|
these differences: |
|
|
|
* :attr:`~django.contrib.auth.models.User.id` is always ``None``. |
|
* :attr:`~django.contrib.auth.models.User.is_staff` and |
|
:attr:`~django.contrib.auth.models.User.is_superuser` are always ``False``. |
|
* :attr:`~django.contrib.auth.models.User.is_active` is always ``False``. |
|
* :attr:`~django.contrib.auth.models.User.groups` and |
|
:attr:`~django.contrib.auth.models.User.user_permissions` are always empty. |
|
* :meth:`~django.contrib.auth.models.User.is_anonymous()` returns ``True`` |
|
instead of ``False``. |
|
* :meth:`~django.contrib.auth.models.User.is_authenticated()` returns |
|
``False`` instead of ``True``. |
|
* :meth:`~django.contrib.auth.models.User.has_perm()` always returns ``False``. |
|
* :meth:`~django.contrib.auth.models.User.set_password()`, |
|
:meth:`~django.contrib.auth.models.User.check_password()`, |
|
:meth:`~django.contrib.auth.models.User.save()`, |
|
:meth:`~django.contrib.auth.models.User.delete()`, |
|
:meth:`~django.contrib.auth.models.User.set_groups()` and |
|
:meth:`~django.contrib.auth.models.User.set_permissions()` raise |
|
:exc:`NotImplementedError`. |
|
|
|
In practice, you probably won't need to use |
|
:class:`~django.contrib.auth.models.AnonymousUser` objects on your own, but |
|
they're used by Web requests, as explained in the next section. |
|
|
|
Creating superusers |
|
------------------- |
|
|
|
.. versionadded:: 1.0 |
|
The ``manage.py createsuperuser`` command is new. |
|
|
|
:djadmin:`manage.py syncdb <syncdb>` prompts you to create a superuser the first time |
|
you run it after adding ``'django.contrib.auth'`` to your |
|
:setting:`INSTALLED_APPS`. If you need to create a superuser at a later date, |
|
you can use a command line utility. |
|
|
|
manage.py createsuperuser --username=joe --email=joe@example.com |
|
|
|
You will be prompted for a password. After you enter one, the user will be |
|
created immediately. If you leave off the :djadminopt:`--username` or the |
|
:djadminopt:`--email` options, it will prompt you for those values. |
|
|
|
If you're using an older release of Django, the old way of creating a superuser |
|
on the command line still works:: |
|
|
|
python /path/to/django/contrib/auth/create_superuser.py |
|
|
|
...where :file:`/path/to` is the path to the Django codebase on your |
|
filesystem. The ``manage.py`` command is preferred because it figures |
|
out the correct path and environment for you. |
|
|
|
.. _auth-profiles: |
|
|
|
Storing additional information about users |
|
------------------------------------------ |
|
|
|
If you'd like to store additional information related to your users, |
|
Django provides a method to specify a site-specific related model -- |
|
termed a "user profile" -- for this purpose. |
|
|
|
To make use of this feature, define a model with fields for the |
|
additional information you'd like to store, or additional methods |
|
you'd like to have available, and also add a |
|
:class:`~django.db.models.Field.ForeignKey` from your model to the |
|
:class:`~django.contrib.auth.models.User` model, specified with ``unique=True`` |
|
to ensure only one instance of your model can be created for each |
|
:class:`~django.contrib.auth.models.User`. |
|
|
|
To indicate that this model is the user profile model for a given |
|
site, fill in the setting :setting:`AUTH_PROFILE_MODULE` with a string |
|
consisting of the following items, separated by a dot: |
|
|
|
1. The (normalized to lower-case) name of the application in which the |
|
user profile model is defined (in other words, an all-lowercase |
|
version of the name which was passed to |
|
:djadmin:`manage.py startapp <startapp>` to create the application). |
|
|
|
2. The (normalized to lower-case) name of the model class. |
|
|
|
For example, if the profile model was a class named ``UserProfile`` |
|
and was defined inside an application named ``accounts``, the |
|
appropriate setting would be:: |
|
|
|
AUTH_PROFILE_MODULE = 'accounts.userprofile' |
|
|
|
When a user profile model has been defined and specified in this |
|
manner, each :class:`~django.contrib.auth.models.User` object will have a |
|
method -- :class:`~django.contrib.auth.models.User.get_profile()` |
|
-- which returns the instance of the user profile model associated |
|
with that :class:`~django.contrib.auth.models.User`. |
|
|
|
For more information, see `Chapter 12 of the Django book`_. |
|
|
|
.. _Chapter 12 of the Django book: http://www.djangobook.com/en/1.0/chapter12/#cn222 |
|
|
|
Authentication in Web requests |
|
============================== |
|
|
|
Until now, this document has dealt with the low-level APIs for manipulating |
|
authentication-related objects. On a higher level, Django can hook this |
|
authentication framework into its system of |
|
:class:`request objects <django.http.HttpRequest>`. |
|
|
|
First, install the |
|
:class:`~django.contrib.sessions.middleware.SessionMiddleware` and |
|
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware` |
|
middlewares by adding them to your :setting:`MIDDLEWARE_CLASSES` setting. See |
|
the :ref:`session documentation <topics-http-sessions>` for more information. |
|
|
|
Once you have those middlewares installed, you'll be able to access |
|
:attr:`request.user <django.http.HttpRequest.user>` in views. |
|
:attr:`request.user <django.http.HttpRequest.user>` will give you a |
|
:class:`~django.contrib.auth.models.User` object representing the currently |
|
logged-in user. If a user isn't currently logged in, |
|
:attr:`request.user <django.http.HttpRequest.user>` will be set to an instance |
|
of :class:`~django.contrib.auth.models.AnonymousUser` (see the previous |
|
section). You can tell them apart with |
|
:meth:`~django.contrib.auth.models.User.is_authenticated()`, like so:: |
|
|
|
if request.user.is_authenticated(): |
|
# Do something for authenticated users. |
|
else: |
|
# Do something for anonymous users. |
|
|
|
How to log a user in |
|
-------------------- |
|
|
|
Django provides two functions in :mod:`django.contrib.auth`: |
|
:func:`~django.contrib.auth.authenticate()` and |
|
:func:`~django.contrib.auth.login()`. |
|
|
|
.. function:: authenticate() |
|
|
|
To authenticate a given username and password, use |
|
:func:`~django.contrib.auth.authenticate()`. It |
|
takes two keyword arguments, ``username`` and ``password``, and it returns |
|
a :class:`~django.contrib.auth.models.User` object if the password is |
|
valid for the given username. If the password is invalid, |
|
:func:`~django.contrib.auth.authenticate()` returns ``None``. Example:: |
|
|
|
from django.contrib.auth import authenticate |
|
user = authenticate(username='john', password='secret') |
|
if user is not None: |
|
if user.is_active: |
|
print "You provided a correct username and password!" |
|
else: |
|
print "Your account has been disabled!" |
|
else: |
|
print "Your username and password were incorrect." |
|
|
|
.. function:: login() |
|
|
|
To log a user in, in a view, use :func:`~django.contrib.auth.login()`. It |
|
takes an :class:`~django.http.HttpRequest` object and a |
|
:class:`~django.contrib.auth.models.User` object. |
|
:func:`~django.contrib.auth.login()` saves the user's ID in the session, |
|
using Django's session framework, so, as mentioned above, you'll need to |
|
make sure to have the session middleware installed. |
|
|
|
This example shows how you might use both |
|
:func:`~django.contrib.auth.authenticate()` and |
|
:func:`~django.contrib.auth.login()`:: |
|
|
|
from django.contrib.auth import authenticate, login |
|
|
|
def my_view(request): |
|
username = request.POST['username'] |
|
password = request.POST['password'] |
|
user = authenticate(username=username, password=password) |
|
if user is not None: |
|
if user.is_active: |
|
login(request, user) |
|
# Redirect to a success page. |
|
else: |
|
# Return a 'disabled account' error message |
|
else: |
|
# Return an 'invalid login' error message. |
|
|
|
.. admonition:: Calling ``authenticate()`` first |
|
|
|
When you're manually logging a user in, you *must* call |
|
:func:`~django.contrib.auth.authenticate()` before you call |
|
:func:`~django.contrib.auth.login()`. |
|
:func:`~django.contrib.auth.authenticate()` |
|
sets an attribute on the :class:`~django.contrib.auth.models.User` noting |
|
which authentication backend successfully authenticated that user (see |
|
the `backends documentation`_ for details), and this information is |
|
needed later during the login process. |
|
|
|
.. _backends documentation: #other-authentication-sources |
|
|
|
Manually checking a user's password |
|
----------------------------------- |
|
|
|
.. function:: check_password() |
|
|
|
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.models.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. |
|
|
|
How to log a user out |
|
--------------------- |
|
|
|
.. function:: logout() |
|
|
|
To log out a user who has been logged in via |
|
:func:`django.contrib.auth.login()`, use |
|
:func:`django.contrib.auth.logout()` within your view. It takes an |
|
:class:`~django.http.HttpRequest` object and has no return value. |
|
Example:: |
|
|
|
from django.contrib.auth import logout |
|
|
|
def logout_view(request): |
|
logout(request) |
|
# Redirect to a success page. |
|
|
|
Note that :func:`~django.contrib.auth.logout()` doesn't throw any errors |
|
if the user wasn't logged in. |
|
|
|
.. versionchanged:: 1.0 |
|
Calling ``logout()`` now cleans session data. |
|
|
|
When you call :func:`~django.contrib.auth.logout()`, the session |
|
data for the current request is completely cleaned out. All existing data |
|
is removed. This is to prevent another person from using the same web |
|
browser to log in and have access to the previous user's session data. |
|
If you want to put anything into the session that will be available to |
|
the user immediately after logging out, do that *after* calling |
|
:func:`django.contrib.auth.logout()`. |
|
|
|
Limiting access to logged-in users |
|
---------------------------------- |
|
|
|
The raw way |
|
~~~~~~~~~~~ |
|
|
|
The simple, raw way to limit access to pages is to check |
|
:meth:`request.user.is_authenticated() |
|
<django.contrib.auth.models.User.is_authenticated()>` and either redirect to a |
|
login page:: |
|
|
|
from django.http import HttpResponseRedirect |
|
|
|
def my_view(request): |
|
if not request.user.is_authenticated(): |
|
return HttpResponseRedirect('/login/?next=%s' % request.path) |
|
# ... |
|
|
|
...or display an error message:: |
|
|
|
def my_view(request): |
|
if not request.user.is_authenticated(): |
|
return render_to_response('myapp/login_error.html') |
|
# ... |
|
|
|
The login_required decorator |
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
|
.. function:: decorators.login_required() |
|
|
|
As a shortcut, you can use the convenient |
|
:func:`~django.contrib.auth.decorators.login_required` decorator:: |
|
|
|
from django.contrib.auth.decorators import login_required |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = login_required(my_view) |
|
|
|
Here's an equivalent example, using the more compact decorator syntax |
|
introduced in Python 2.4:: |
|
|
|
from django.contrib.auth.decorators import login_required |
|
|
|
@login_required |
|
def my_view(request): |
|
# ... |
|
|
|
In the Django development version, |
|
:func:`~django.contrib.auth.decorators.login_required` also takes an |
|
optional ``redirect_field_name`` parameter. Example:: |
|
|
|
from django.contrib.auth.decorators import login_required |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = login_required(redirect_field_name='redirect_to')(my_view) |
|
|
|
Again, an equivalent example of the more compact decorator syntax |
|
introduced in Python 2.4:: |
|
|
|
from django.contrib.auth.decorators import login_required |
|
|
|
@login_required(redirect_field_name='redirect_to') |
|
def my_view(request): |
|
# ... |
|
|
|
:func:`~django.contrib.auth.decorators.login_required` does the following: |
|
|
|
* If the user isn't logged in, redirect to |
|
:setting:`settings.LOGIN_URL <LOGIN_URL>` (``/accounts/login/`` by |
|
default), passing the current absolute URL in the query string as |
|
``next`` or the value of ``redirect_field_name``. For example: |
|
``/accounts/login/?next=/polls/3/``. |
|
|
|
* If the user is logged in, execute the view normally. The view code |
|
is free to assume the user is logged in. |
|
|
|
Note that you'll need to map the appropriate Django view to |
|
:setting:`settings.LOGIN_URL <LOGIN_URL>`. For example, using the defaults, add |
|
the following line to your URLconf:: |
|
|
|
(r'^accounts/login/$', 'django.contrib.auth.views.login'), |
|
|
|
.. function:: views.login() |
|
|
|
Here's what ``django.contrib.auth.views.login`` does: |
|
|
|
* If called via ``GET``, it displays a login form that POSTs to the same |
|
URL. More on this in a bit. |
|
|
|
* If called via ``POST``, it tries to log the user in. If login is |
|
successful, the view redirects to the URL specified in ``next``. If |
|
``next`` isn't provided, it redirects to :setting:`settings.LOGIN_REDIRECT_URL <LOGIN_REDIRECT_URL>` |
|
(which defaults to ``/accounts/profile/``). If login isn't successful, |
|
it redisplays the login form. |
|
|
|
It's your responsibility to provide the login form in a template called |
|
``registration/login.html`` by default. This template gets passed three |
|
template context variables: |
|
|
|
* ``form``: A :class:`~django.forms.Form` object representing the |
|
login form. See the :ref:`forms documentation <topics-forms-index>` |
|
for more on ``FormWrapper`` objects. |
|
|
|
* ``next``: The URL to redirect to after successful login. This may contain |
|
a query string, too. |
|
|
|
* ``site_name``: The name of the current |
|
:class:`~django.contrib.sites.models.Site``, according to the |
|
:setting:`SITE_ID` setting. If you're using the Django development version |
|
and you don't have the site framework installed, this will be set to the |
|
value of ``request.META['SERVER_NAME']``. For more on sites, see |
|
:ref:`ref-contrib-sites`. |
|
|
|
If you'd prefer not to call the template :file:`registration/login.html`, |
|
you can pass the ``template_name`` parameter via the extra arguments to |
|
the view in your URLconf. For example, this URLconf line would use |
|
:file:`myapp/login.html` instead:: |
|
|
|
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), |
|
|
|
Here's a sample :file:`registration/login.html` template you can use as a |
|
starting point. It assumes you have a :file:`base.html` template that |
|
defines a ``content`` block:: |
|
|
|
{% extends "base.html" %} |
|
|
|
{% block content %} |
|
|
|
{% if form.errors %} |
|
<p>Your username and password didn't match. Please try again.</p> |
|
{% endif %} |
|
|
|
<form method="post" action="."> |
|
<table> |
|
<tr><td>{{ form.username.label_tag }}</td><td>{{ form.username }}</td></tr> |
|
<tr><td>{{ form.password.label_tag }}</td><td>{{ form.password }}</td></tr> |
|
</table> |
|
|
|
<input type="submit" value="login" /> |
|
<input type="hidden" name="next" value="{{ next }}" /> |
|
</form> |
|
|
|
{% endblock %} |
|
|
|
.. _forms documentation: ../forms/ |
|
.. _site framework docs: ../sites/ |
|
|
|
Other built-in views |
|
-------------------- |
|
|
|
In addition to the ``login`` view, the authentication system includes a |
|
few other useful built-in views: |
|
|
|
.. function:: django.contrib.auth.views.logout |
|
|
|
Logs a user out. |
|
|
|
**Optional arguments:** |
|
|
|
* ``template_name``: The full name of a template to display after |
|
logging the user out. This will default to |
|
:file:`registration/logged_out.html` if no argument is supplied. |
|
|
|
**Template context:** |
|
|
|
* ``title``: The string "Logged out", localized. |
|
|
|
.. function:: django.contrib.auth.views.logout_then_login |
|
|
|
Logs a user out, then redirects to the login page. |
|
|
|
**Optional arguments:** |
|
|
|
* ``login_url``: The URL of the login page to redirect to. This |
|
will default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not |
|
supplied. |
|
|
|
.. function:: django.contrib.auth.views.password_change |
|
|
|
Allows a user to change their password. |
|
|
|
**Optional arguments:** |
|
|
|
* ``template_name``: The full name of a template to use for |
|
displaying the password change form. This will default to |
|
:file:`registration/password_change_form.html` if not supplied. |
|
|
|
**Template context:** |
|
|
|
* ``form``: The password change form. |
|
|
|
.. function:: django.contrib.auth.views.password_change_done |
|
|
|
The page shown after a user has changed their password. |
|
|
|
**Optional arguments:** |
|
|
|
* ``template_name``: The full name of a template to use. This will |
|
default to :file:`registration/password_change_done.html` if not |
|
supplied. |
|
|
|
.. function:: django.contrib.auth.views.password_reset |
|
|
|
Allows a user to reset their password, and sends them the new password |
|
in an e-mail. |
|
|
|
**Optional arguments:** |
|
|
|
* ``template_name``: The full name of a template to use for |
|
displaying the password reset form. This will default to |
|
:file:`registration/password_reset_form.html` if not supplied. |
|
|
|
* ``email_template_name``: The full name of a template to use for |
|
generating the e-mail with the new password. This will default to |
|
:file:`registration/password_reset_email.html` if not supplied. |
|
|
|
**Template context:** |
|
|
|
* ``form``: The form for resetting the user's password. |
|
|
|
.. function:: django.contrib.auth.views.password_reset_done |
|
|
|
The page shown after a user has reset their password. |
|
|
|
**Optional arguments:** |
|
|
|
* ``template_name``: The full name of a template to use. This will |
|
default to :file:`registration/password_reset_done.html` if not |
|
supplied. |
|
|
|
.. function:: django.contrib.auth.views.redirect_to_login |
|
|
|
Redirects to the login page, and then back to another URL after a |
|
successful login. |
|
|
|
**Required arguments:** |
|
|
|
* ``next``: The URL to redirect to after a successful login. |
|
|
|
**Optional arguments:** |
|
|
|
* ``login_url``: The URL of the login page to redirect to. This |
|
will default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not |
|
supplied. |
|
|
|
Built-in forms |
|
--------------------- |
|
|
|
If you don't want to use the built-in views, but want the convenience |
|
of not having to write forms for this functionality, the authentication |
|
system provides several built-in forms: |
|
|
|
* :class:`django.contrib.auth.forms.AdminPasswordChangeForm`: A form used |
|
in the admin interface to change a user's password. |
|
|
|
* :class:`django.contrib.auth.forms.AuthenticationForm`: A form for |
|
logging a user in. |
|
|
|
* :class:`django.contrib.auth.forms.PasswordChangeForm`: A form for |
|
allowing a user to change their password. |
|
|
|
* :class:`django.contrib.auth.forms.PasswordResetForm`: A form for |
|
resetting a user's password and e-mailing the new password to them. |
|
|
|
* :class:`django.contrib.auth.forms.UserCreationForm`: A form for creating |
|
a new user. |
|
|
|
Limiting access to logged-in users that pass a test |
|
--------------------------------------------------- |
|
|
|
To limit access based on certain permissions or some other test, you'd do |
|
essentially the same thing as described in the previous section. |
|
|
|
The simple way is to run your test on |
|
:attr:`request.user <django.http.HttpRequest.user>` in the view directly. |
|
For example, this view checks to make sure the user is logged in and has the |
|
permission ``polls.can_vote``:: |
|
|
|
def my_view(request): |
|
if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')): |
|
return HttpResponse("You can't vote in this poll.") |
|
# ... |
|
|
|
.. function:: decorators.user_passes_test() |
|
|
|
As a shortcut, you can use the convenient ``user_passes_test`` decorator:: |
|
|
|
from django.contrib.auth.decorators import user_passes_test |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view) |
|
|
|
We're using this particular test as a relatively simple example. However, |
|
if you just want to test whether a permission is available to a user, you |
|
can use the :func:`django.contrib.auth.decorators.permission_required()` |
|
decorator, described later in this document. |
|
|
|
Here's the same thing, using Python 2.4's decorator syntax:: |
|
|
|
from django.contrib.auth.decorators import user_passes_test |
|
|
|
@user_passes_test(lambda u: u.has_perm('polls.can_vote')) |
|
def my_view(request): |
|
# ... |
|
|
|
:func:`~django.contrib.auth.decorators.user_passes_test` takes a required |
|
argument: a callable that takes a |
|
:class:`~django.contrib.auth.models.User` object and returns ``True`` if |
|
the user is allowed to view the page. Note that |
|
:func:`~django.contrib.auth.decorators.user_passes_test` does not |
|
automatically check that the :class:`~django.contrib.auth.models.User` is |
|
not anonymous. |
|
|
|
:func:`~django.contrib.auth.decorators.user_passes_test()` takes an |
|
optional ``login_url`` argument, which lets you specify the URL for your |
|
login page (:setting:`settings.LOGIN_URL <LOGIN_URL>` by default). |
|
|
|
Example in Python 2.3 syntax:: |
|
|
|
from django.contrib.auth.decorators import user_passes_test |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view) |
|
|
|
Example in Python 2.4 syntax:: |
|
|
|
from django.contrib.auth.decorators import user_passes_test |
|
|
|
@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/') |
|
def my_view(request): |
|
# ... |
|
|
|
The permission_required decorator |
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
|
.. function:: decorators.permission_required() |
|
|
|
It's a relatively common task to check whether a user has a particular |
|
permission. For that reason, Django provides a shortcut for that case: the |
|
:func:`~django.contrib.auth.decorators.permission_required()` decorator. |
|
Using this decorator, the earlier example can be written as:: |
|
|
|
from django.contrib.auth.decorators import permission_required |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = permission_required('polls.can_vote')(my_view) |
|
|
|
Note that :func:`~django.contrib.auth.decorators.permission_required()` |
|
also takes an optional ``login_url`` parameter. Example:: |
|
|
|
from django.contrib.auth.decorators import permission_required |
|
|
|
def my_view(request): |
|
# ... |
|
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view) |
|
|
|
As in the ``login_required`` decorator, ``login_url`` defaults to |
|
:setting:`settings.LOGIN_URL <LOGIN_URL>`. |
|
|
|
Limiting access to generic views |
|
-------------------------------- |
|
|
|
To limit access to a :ref:`generic view <ref-generic-views>`, write a thin |
|
wrapper around the view, and point your URLconf to your wrapper instead of the |
|
generic view itself. For example:: |
|
|
|
from django.views.generic.date_based import object_detail |
|
|
|
@login_required |
|
def limited_object_detail(*args, **kwargs): |
|
return object_detail(*args, **kwargs) |
|
|
|
Permissions |
|
=========== |
|
|
|
Django comes with a simple permissions system. It provides a way to assign |
|
permissions to specific users and groups of users. |
|
|
|
It's used by the Django admin site, but you're welcome to use it in your own |
|
code. |
|
|
|
The Django admin site uses permissions as follows: |
|
|
|
* Access to view the "add" form and add an object is limited to users with |
|
the "add" permission for that type of object. |
|
* Access to view the change list, view the "change" form and change an |
|
object is limited to users with the "change" permission for that type of |
|
object. |
|
* Access to delete an object is limited to users with the "delete" |
|
permission for that type of object. |
|
|
|
Permissions are set globally per type of object, not per specific object |
|
instance. For example, it's possible to say "Mary may change news stories," but |
|
it's not currently possible to say "Mary may change news stories, but only the |
|
ones she created herself" or "Mary may only change news stories that have a |
|
certain status, publication date or ID." The latter functionality is something |
|
Django developers are currently discussing. |
|
|
|
Default permissions |
|
------------------- |
|
|
|
When ``django.contrib.auth`` is listed in your :setting:`INSTALLED_APPS` |
|
setting, it will ensure that three default permissions -- add, change |
|
and delete -- are created for each Django model defined in one of your |
|
installed applications. |
|
|
|
These permissions will be created when you run |
|
:djadmin:`manage.py syncdb <syncdb>`; the first time you run ``syncdb`` after |
|
adding ``django.contrib.auth`` to :setting:`INSTALLED_APPS`, the default |
|
permissions will be created for all previously-installed models, as well as |
|
for any new models being installed at that time. Afterward, it will create |
|
default permissions for new models each time you run |
|
:djadmin:`manage.py syncdb <syncdb>`. |
|
|
|
.. _custom-permissions: |
|
|
|
Custom permissions |
|
------------------ |
|
|
|
To create custom permissions for a given model object, use the ``permissions`` |
|
:ref:`model Meta attribute <meta-options>`. |
|
|
|
This example model creates three custom permissions:: |
|
|
|
class USCitizen(models.Model): |
|
# ... |
|
class Meta: |
|
permissions = ( |
|
("can_drive", "Can drive"), |
|
("can_vote", "Can vote in elections"), |
|
("can_drink", "Can drink alcohol"), |
|
) |
|
|
|
The only thing this does is create those extra permissions when you run |
|
:djadmin:`manage.py syncdb <syncdb>`. |
|
|
|
API reference |
|
------------- |
|
|
|
.. class:: models.Permission |
|
|
|
Just like users, permissions are implemented in a Django model that lives in |
|
`django/contrib/auth/models.py`_. |
|
|
|
.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py |
|
|
|
Fields |
|
~~~~~~ |
|
|
|
:class:`~django.contrib.auth.models.Permission` objects have the following |
|
fields: |
|
|
|
.. attribute:: models.Permission.name |
|
|
|
Required. 50 characters or fewer. Example: ``'Can vote'``. |
|
|
|
.. attribute:: models.Permission.content_type |
|
|
|
Required. A reference to the ``django_content_type`` database table, |
|
which contains a record for each installed Django model. |
|
|
|
.. attribute:: models.Permission.codename |
|
|
|
Required. 100 characters or fewer. Example: ``'can_vote'``. |
|
|
|
Methods |
|
~~~~~~~ |
|
|
|
:class:`~django.contrib.auth.models.Permission` objects have the standard |
|
data-access methods like any other :ref:`Django model <ref-models-instances>`. |
|
|
|
Authentication data in templates |
|
================================ |
|
|
|
The currently logged-in user and his/her permissions are made available in the |
|
:ref:`template context <ref-templates-api>` when you use |
|
:class:`~django.template.context.RequestContext`. |
|
|
|
.. admonition:: Technicality |
|
|
|
Technically, these variables are only made available in the template context |
|
if you use :class:`~django.template.context.RequestContext` *and* your |
|
:setting:`TEMPLATE_CONTEXT_PROCESSORS` setting contains |
|
``"django.core.context_processors.auth"``, which is default. For more, see |
|
the :ref:`RequestContext docs <subclassing-context-requestcontext>`. |
|
|
|
Users |
|
----- |
|
|
|
The currently logged-in user, either a |
|
:class:`~django.contrib.auth.models.User` instance or an |
|
:class:`~django.contrib.auth.models.AnonymousUser` instance, is stored in the |
|
template variable ``{{ user }}``:: |
|
|
|
{% if user.is_authenticated %} |
|
<p>Welcome, {{ user.username }}. Thanks for logging in.</p> |
|
{% else %} |
|
<p>Welcome, new user. Please log in.</p> |
|
{% endif %} |
|
|
|
Permissions |
|
----------- |
|
|
|
The currently logged-in user's permissions are stored in the template variable |
|
``{{ perms }}``. This is an instance of |
|
:class:`django.core.context_processors.PermWrapper`, which is a |
|
template-friendly proxy of permissions. |
|
|
|
In the ``{{ perms }}`` object, single-attribute lookup is a proxy to |
|
:meth:`User.has_module_perms <django.contrib.auth.models.User.has_module_perms>`. |
|
This example would display ``True`` if the logged-in user had any permissions |
|
in the ``foo`` app:: |
|
|
|
{{ perms.foo }} |
|
|
|
Two-level-attribute lookup is a proxy to |
|
:meth:`User.has_perm <django.contrib.auth.models.User.has_perm>`. This example |
|
would display ``True`` if the logged-in user had the permission |
|
``foo.can_vote``:: |
|
|
|
{{ perms.foo.can_vote }} |
|
|
|
Thus, you can check permissions in template ``{% if %}`` statements:: |
|
|
|
{% if perms.foo %} |
|
<p>You have permission to do something in the foo app.</p> |
|
{% if perms.foo.can_vote %} |
|
<p>You can vote!</p> |
|
{% endif %} |
|
{% if perms.foo.can_drive %} |
|
<p>You can drive!</p> |
|
{% endif %} |
|
{% else %} |
|
<p>You don't have permission to do anything in the foo app.</p> |
|
{% endif %} |
|
|
|
Groups |
|
====== |
|
|
|
Groups are a generic way of categorizing users so you can apply permissions, or |
|
some other label, to those users. A user can belong to any number of groups. |
|
|
|
A user in a group automatically has the permissions granted to that group. For |
|
example, if the group ``Site editors`` has the permission |
|
``can_edit_home_page``, any user in that group will have that permission. |
|
|
|
Beyond permissions, groups are a convenient way to categorize users to give |
|
them some label, or extended functionality. For example, you could create a |
|
group ``'Special users'``, and you could write code that could, say, give them |
|
access to a members-only portion of your site, or send them members-only e-mail |
|
messages. |
|
|
|
Messages |
|
======== |
|
|
|
The message system is a lightweight way to queue messages for given users. |
|
|
|
A message is associated with a :class:`~django.contrib.auth.models.User`. |
|
There's no concept of expiration or timestamps. |
|
|
|
Messages are used by the Django admin after successful actions. For example, |
|
``"The poll Foo was created successfully."`` is a message. |
|
|
|
The API is simple: |
|
|
|
.. method:: models.User.message_set.create(message) |
|
|
|
To create a new message, use |
|
``user_obj.message_set.create(message='message_text')``. |
|
|
|
To retrieve/delete messages, use |
|
:meth:`user_obj.get_and_delete_messages() <django.contrib.auth.models.User.get_and_delete_messages>`, |
|
which returns a list of ``Message`` objects in the user's queue (if any) |
|
and deletes the messages from the queue. |
|
|
|
In this example view, the system saves a message for the user after creating |
|
a playlist:: |
|
|
|
def create_playlist(request, songs): |
|
# Create the playlist with the given songs. |
|
# ... |
|
request.user.message_set.create(message="Your playlist was added successfully.") |
|
return render_to_response("playlists/create.html", |
|
context_instance=RequestContext(request)) |
|
|
|
When you use :class:`~django.template.context.RequestContext`, the currently |
|
logged-in user and his/her messages are made available in the |
|
:ref:`template context <ref-templates-api>` as the template variable |
|
``{{ messages }}``. Here's an example of template code that displays messages:: |
|
|
|
{% if messages %} |
|
<ul> |
|
{% for message in messages %} |
|
<li>{{ message }}</li> |
|
{% endfor %} |
|
</ul> |
|
{% endif %} |
|
|
|
Note that :class:`~django.template.context.RequestContext` calls |
|
:meth:`~django.contrib.auth.models.User.get_and_delete_messages` behind the |
|
scenes, so any messages will be deleted even if you don't display them. |
|
|
|
Finally, note that this messages framework only works with users in the user |
|
database. To send messages to anonymous users, use the |
|
:ref:`session framework <topics-http-sessions>`. |
|
|
|
.. _authentication-backends: |
|
|
|
Other authentication sources |
|
============================ |
|
|
|
The authentication that comes with Django is good enough for most common cases, |
|
but you may have the need to hook into another authentication source -- that |
|
is, another source of usernames and passwords or authentication methods. |
|
|
|
For example, your company may already have an LDAP setup that stores a username |
|
and password for every employee. It'd be a hassle for both the network |
|
administrator and the users themselves if users had separate accounts in LDAP |
|
and the Django-based applications. |
|
|
|
So, to handle situations like this, the Django authentication system lets you |
|
plug in another authentication sources. You can override Django's default |
|
database-based scheme, or you can use the default system in tandem with other |
|
systems. |
|
|
|
Specifying authentication backends |
|
---------------------------------- |
|
|
|
Behind the scenes, Django maintains a list of "authentication backends" that it |
|
checks for authentication. When somebody calls |
|
:func:`django.contrib.auth.authenticate()` -- as described in "How to log a |
|
user in" above -- Django tries authenticating across all of its authentication |
|
backends. If the first authentication method fails, Django tries the second |
|
one, and so on, until all backends have been attempted. |
|
|
|
The list of authentication backends to use is specified in the |
|
:setting:`AUTHENTICATION_BACKENDS` setting. This should be a tuple of Python |
|
path names that point to Python classes that know how to authenticate. These |
|
classes can be anywhere on your Python path. |
|
|
|
By default, :setting:`AUTHENTICATION_BACKENDS` is set to:: |
|
|
|
('django.contrib.auth.backends.ModelBackend',) |
|
|
|
That's the basic authentication scheme that checks the Django users database. |
|
|
|
The order of :setting:`AUTHENTICATION_BACKENDS` matters, so if the same username |
|
and password is valid in multiple backends, Django will stop processing at the |
|
first positive match. |
|
|
|
Writing an authentication backend |
|
--------------------------------- |
|
|
|
An authentication backend is a class that implements two methods: |
|
``get_user(user_id)`` and ``authenticate(**credentials)``. |
|
|
|
The ``get_user`` method takes a ``user_id`` -- which could be a username, |
|
database ID or whatever -- and returns a ``User`` object. |
|
|
|
The ``authenticate`` method takes credentials as keyword arguments. Most of |
|
the time, it'll just look like this:: |
|
|
|
class MyBackend: |
|
def authenticate(self, username=None, password=None): |
|
# Check the username/password and return a User. |
|
|
|
But it could also authenticate a token, like so:: |
|
|
|
class MyBackend: |
|
def authenticate(self, token=None): |
|
# Check the token and return a User. |
|
|
|
Either way, ``authenticate`` should check the credentials it gets, and it |
|
should return a ``User`` object that matches those credentials, if the |
|
credentials are valid. If they're not valid, it should return ``None``. |
|
|
|
The Django admin system is tightly coupled to the Django ``User`` object |
|
described at the beginning of this document. For now, the best way to deal with |
|
this is to create a Django ``User`` object for each user that exists for your |
|
backend (e.g., in your LDAP directory, your external SQL database, etc.) You |
|
can either write a script to do this in advance, or your ``authenticate`` |
|
method can do it the first time a user logs in. |
|
|
|
Here's an example backend that authenticates against a username and password |
|
variable defined in your ``settings.py`` file and creates a Django ``User`` |
|
object the first time a user authenticates:: |
|
|
|
from django.conf import settings |
|
from django.contrib.auth.models import User, check_password |
|
|
|
class SettingsBackend: |
|
""" |
|
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. |
|
|
|
Use the login name, and a hash of the password. For example: |
|
|
|
ADMIN_LOGIN = 'admin' |
|
ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' |
|
""" |
|
def authenticate(self, username=None, password=None): |
|
login_valid = (settings.ADMIN_LOGIN == username) |
|
pwd_valid = check_password(password, settings.ADMIN_PASSWORD) |
|
if login_valid and pwd_valid: |
|
try: |
|
user = User.objects.get(username=username) |
|
except User.DoesNotExist: |
|
# Create a new user. Note that we can set password |
|
# to anything, because it won't be checked; the password |
|
# from settings.py will. |
|
user = User(username=username, password='get from settings.py') |
|
user.is_staff = True |
|
user.is_superuser = True |
|
user.save() |
|
return user |
|
return None |
|
|
|
def get_user(self, user_id): |
|
try: |
|
return User.objects.get(pk=user_id) |
|
except User.DoesNotExist: |
|
return None |
|
|
|
Handling authorization in custom backends |
|
----------------------------------------- |
|
|
|
Custom auth backends can provide their own permissions. |
|
|
|
The user model will delegate permission lookup functions |
|
(:meth:`~django.contrib.auth.models.User.get_group_permissions()`, |
|
:meth:`~django.contrib.auth.models.User.get_all_permissions()`, |
|
:meth:`~django.contrib.auth.models.User.has_perm()`, and |
|
:meth:`~django.contrib.auth.models.User.has_module_perms()`) to any |
|
authentication backend that implements these functions. |
|
|
|
The permissions given to the user will be the superset of all permissions |
|
returned by all backends. That is, Django grants a permission to a user that |
|
any one backend grants. |
|
|
|
The simple backend above could implement permissions for the magic admin |
|
fairly simply:: |
|
|
|
class SettingsBackend: |
|
|
|
# ... |
|
|
|
def has_perm(self, user_obj, perm): |
|
if user_obj.username == settings.ADMIN_LOGIN: |
|
return True |
|
else: |
|
return False |
|
|
|
This gives full permissions to the user granted access in the above example. |
|
Notice that the backend auth functions all take the user object as an argument, |
|
and they also accept the same arguments given to the associated |
|
:class:`django.contrib.auth.models.User` functions. |
|
|
|
A full authorization implementation can be found in |
|
`django/contrib/auth/backends.py`_, which is the default backend and queries |
|
the ``auth_permission`` table most of the time. |
|
|
|
.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
|
|
|