Django содержит систему идентификации пользователей, предоставляя работу с пользователями, группами пользователей, правами и сессиями пользователей работающими через куки(пер. cookie-based user sessions). Этот раздел описывает как эта система работает.
Система идентификации пользователей состоит из:
Пользователи
Права: Булево значение (да/не) определяющее имеет ли пользователь права на различные действия.
Группы: предоставляют возможность назначить множество прав нескольким пользователям.
Система идентификации пользователей в Django представлена приложением django.contrib.auth. Для его установки выполните следующие действия:
Добавьте 'django.contrib.auth' и 'django.contrib.contenttypes' в настройку проекта INSTALLED_APPS. (Модель Permission в django.contrib.auth зависит от django.contrib.contenttypes.)
Выполните команду manage.py syncdb.
Файл settings.py, создаваемый командой django-admin.py startproject, для удобства уже содержит 'django.contrib.auth' и 'django.contrib.contenttypes' в INSTALLED_APPS. Если INSTALLED_APPS`уже содержит эти приложения, вы можете смело запускать :djadmin:`manage.py syncdb; вы можете выполнять эту команду сколько угодно раз, будут выполнены только необходимые изменния.
Команда syncdb создаст необходимые таблицы в базе данных, создаст при необходимости объекты прав для всех установленных приложений и предложит создать суперпользователя при первом запуске.
Теперь все работает.
Объекты User содержат следующие поля:
Обязательное. До 30 символов. Только буквы, цифры и подчеркивание.
Необязательное. До 30 символов.
Необязательное. До 30 символов.
Необязательное. Email адрес.
Обязательное. Хэш и метаданные о пароле. (Django не сохраняет открытый пароль.) Пароль может быть любой длинны и содержать любое количество символов. Смотрите раздел “Пароли” ниже.
Булево. Указывает имеет ли пользователь доступ к интерфейсу администратора.
Булево. Указывает активный аккаунт или нет. Советуем устанавливать это поле в False вместо удаления; если в вашем приложение существуют связи с моделью пользователя, они не будет сломаны.
Это поле не контролирует может пользователь войти или нет. Бэкэнд идентификации не проверяет значение is_active, по этому если вы хотите ограничить вход для пользователей с is_active равным False, делайте это в собственном представлении входа. Однако, класс формы AuthenticationForm используемый в представлении login() выполняет проверку is_active, аналогично и метод проверки прав has_perm() и вход в интерфейс администратора Django. Все эти методы/функции вернут False для неактивных пользователей.
Булево. Определяет, что пользователь имеет все права без явного их присвоения пользователю.
Время последнего входа пользователя. По умолчанию устанавливается в текущее время.
Время создания аккаунта. По умолчанию устанавливается в текущее время при создании аккаунта.
Объекты User содержат две связи многое-ко-многим: groups и user_permissions. Объекты User могут обращаться к связанным объектам так же как и другие модели Django:
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()
В дополнении к этим автоматически созданным методам User содержит следующие методы:
Всегда возвращает False. Используется для распознания объектов User и AnonymousUser. Лучше использовать is_authenticated().
Всегда возвращает True. Указывает что пользователь идентифицирован. Не учитывает никаких прав и не проверяет активный ли пользователь - указывает только то, что пользователь указал верный пароль и имя пользователя.
Возвращает first_name и last_name разделенные пробелом.
Устанавливает пароль в указанную строку, выполняет хэширование пароля. Не сохраняет объект User.
Возвращает True если переданная строка является правильным паролем. (Выполняет хэширование перед сравнением паролей.)
Указывает что пользователь не указал пароль. Не аналогично пустому паролю. check_password() никогда не вернет True для этого пользователя. Не сохраняет объект User.
Можно использовать если идентификация пользователя использует сторонний механизм и не хранит пароли в базе данных, например каталог LDAP.
Возвращает False если был вызван метод set_unusable_password() для этого пользователя.
Возвращает множество строк представляющие права пользователя добавленные с помощью групп.
Если указан obj, возвращает права только для указанного объекта.
Возвращает множество строк представляющие все права пользователя, с учетом групп.
Если указан obj, возвращает права только для указанного объекта.
Возвращает True если пользователь имеет указанное право доступа, где право указывает в формате "<app label>.<permission codename>". (смотрите раздел Права пользователя ниже). Если пользователь неактивный, метод всегда возвращает False.
Если указан obj, метод проверит наличие права доступа для этого объекта, а не модели.
Возвращает True, если пользователь имеет все указанные права, права указанны в формате "<app label>.<permission codename>". Если пользователь неактивный, метод вернет False.
Если передан obj, метод будет проверять этот объект, а не модель.
Возвращает True если пользователь имеет хотя бы одно право доступа для указанного приложения. Если пользователь неактивный, метод вернет False.
Шлет email пользователю. Если from_email равен None, Django использует настройку DEFAULT_FROM_EMAIL.
Возвращает профиль пользователя. Вызывает django.contrib.auth.models.SiteProfileNotAvailable если профиль не настроен в текущем проекте, или django.core.exceptions.ObjectDoesNotExist если профиль пользователя не существует. Подробнее о профилях пользователя смотрите в разделе storing additional user information ниже.
Модель User использует менеджер, который предоставляет дополнительные методы:
Создает, сохраняет и возвращает User.
username и password равны соответствующим аргумнтам. Домен в email автоматически конвертируется в нижний регистр, созданный объект User будет с атрибутом is_active равным True.
Если пароль не указан, будет вызван метод set_unusable_password().
Примеры смотрите в `Creating users`_.
Возвращает случайный пароль указанной длинны из указанных символов. (Заметим что значение allowed_chars по умолчанию не содержит символы, которые могут озадачить пользователя:
i, l, I, и 1 (“i” в нижнем регистре, “L” в нижнем регистре, “i” в верхнем регистре и цифра один)
o, O, и 0 (“o” в верхнем регистре, “o” в нижнем регистре и ноль)
Самый простой способ создать пользователя - вызывать метод create_user():
>>> 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()
Вы так же можете создать пользователя с помощью интерфейса администратора. Предположим что вы уже настроили его и подключили к URL-у /admin/, Страница для добавления пользователя будет находиться по адресу /admin/auth/user/add/. Вы так же должны видеть ссылку “Users” в разделе “Auth” на главной странице интерфейса администратора. Страница добавления пользователя отличается от стандартной страницы добавления в интерфейсе администратора, вы должны указать пароль и имя пользователя перед редактированием пользователя.
Так же помните: если вы хотите создавать пользователей используя интерфейс администратора, вам необходимо добавить своему аккаунту права добавления и редактирования пользователей (то есть, права “Add user” и “Change user”). Если ваш аккаунт имеет право добавлять но не редактировать пользователя, вы не сможете добавлять пользователей. Почему? Потому что если у вас есть права добавлять пользователя, вы можете создать суперпользователя и с его помощью редактировать других пользователей. По этому Django требует права добавлять и редактировать.
manage.py changepassword *username* позволяет изменить пароль пользователя через консоль. Эта команда предлагает ввести пароль для указанно пользователя, вы должны ввести пароль дважды. Если введенные пароли совпадают, он будет изменен. Если пользователь не указан, команда попытается изменить пароль пользователю чье имя совпадает с текущим пользователем.
Вы так же можете сменить пароль программно, используя set_password():
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username__exact='john')
>>> u.set_password('new password')
>>> u.save()
Не изменяйте атрибут password явно, если вы не знаете что делаете. Это объясняется в следующем разделе.
Атрибут password объекта User содержит строку в формате:
algorithm$hash
Она состоит из алгоритма и хэша разделенных знаком доллара. Django поддерживает несколько алгоритмов, подробнее смотрите ниже. Хэш - результат выполнения алгоритма над паролем.
По умолчанию, Django использует алгоритм PBKDF2 с SHA256 хэшом – механизм рекомендованный NIST. Этого должно быть достаточно для большинства пользователей: механизм достаточно защищен и требует больших вычислительных ресурсов для взлома.
Одна, если это необходимо, вы можете выбрать другой алгоритм, или использовать собственный. Опять же, большинству пользователей не придется этого делать – если вы не уверены, скорее всего вам не нужно что-либо менять.
Django выбирает алгоритм в соответствии с настройкой PASSWORD_HASHERS. Настройка содержит список хэширующих алгоритмов, которые поддерживает проект. Первый элемент списка (то есть settings.PASSWORD_HASHERS[0]) будет использован для хранения паролей, и все остальные элементы могут быть использованы при проверке паролей. Это означает что если вы хотите использовать другой алгоритм, вам необходимо добавить его в начало списка PASSWORD_HASHERS.
Значение по умолчанию для PASSWORD_HASHERS:
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',
)
Это означает что Django будет использовать PBKDF2 для хранения паролей, но для проверки сохраненных паролей использует PBKDF2SHA1, bcrypt, SHA1, и др. Следующие несколько разделов описывают как продвинутые пользователи могут поменять эту настройку.
Bcrypt – популярный алгоритм для шифрования паролей, специально создан для долговременного хранения паролей. Не используется Django по умолчанию так как требует использования сторонних библиотек, но так как он может пригодиться для большинства пользователей, Django позволяет использовать bcrypt с минимальными усилиями.
Что бы использовать Bcrypt по умолчанию, выполните следующие действия:
Установите библиотеку py-bcrypt (выполнив sudo pip install py-bcrypt, или скачав библиотеку и установив ее с помощью python setup.py install).
Измените PASSWORD_HASHERS добавив в начало списка BCryptPasswordHasher. Вот что должно получиться:
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',
)
(Необходимо сохранить остальные элементы списка, иначе Django не сможет обновить пароли, подробности смотрите ниже).
Это все – теперь Django будет использовать Bcrypt как алгоритм по умолчанию для хранения паролей.
Other bcrypt implementations
Существуют и другие реализации использования bcrypt с Django. Но они не совсем совместимы с текущей реализацией поддержки bcrypt. Для обновления вам необходимо изменить хэши в базе данных в формат bcrypt$(результат алгоритма). Например: bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy.
The PDKDF2 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 PDKDF2 algorithm:
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.
Add your new hasher as the first entry in 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.
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 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.
django.contrib.auth.models.AnonymousUser – это класс, который реализует интерфейс класса django.contrib.auth.models.User, с следующими отличиями:
id всегда равен None.
is_staff и is_superuser всегда равны False.
is_active всегда False.
groups и user_permissions всегда пустные.
is_anonymous() возвращает True вместо False.
is_authenticated() возвращает False вместо True.
set_password(), check_password(), save(), delete(), set_groups() и set_permissions() вызывают исключение NotImplementedError.
На практике вам не придется использовать объект AnonymousUser, он используется объекте запроса, как будет описано в следующем разделе.
manage.py syncdb prompts you to create a superuser the first time you run it after adding 'django.contrib.auth' to your 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 --username or the --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 /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.
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 OneToOneField named user from your model to the User model. This will ensure only one instance of your model can be created for each User. For example:
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
To indicate that this model is the user profile model for a given site, fill in the setting AUTH_PROFILE_MODULE with a string consisting of the following items, separated by a dot:
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 User object will have a method – get_profile() – which returns the instance of the user profile model associated with that User.
The method get_profile() does not create a profile if one does not exist. You need to register a handler for the User model’s django.db.models.signals.post_save signal and, in the handler, if created is True, create the associated user profile:
# in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
# definition of UserProfile from above
# ...
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
См.также
Сигналы for more information on Django’s signal dispatcher.
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 request objects.
First, install the SessionMiddleware and AuthenticationMiddleware middlewares by adding them to your MIDDLEWARE_CLASSES setting. See the session documentation for more information.
Once you have those middlewares installed, you’ll be able to access request.user in views. request.user will give you a User object representing the currently logged-in user. If a user isn’t currently logged in, request.user will be set to an instance of AnonymousUser (see the previous section). You can tell them apart with is_authenticated(), like so:
if request.user.is_authenticated():
# Do something for authenticated users.
else:
# Do something for anonymous users.
Django provides two functions in django.contrib.auth: authenticate() and login().
To authenticate a given username and password, use authenticate(). It takes two keyword arguments, username and password, and it returns a User object if the password is valid for the given username. If the password is invalid, 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."
To log a user in, in a view, use login(). It takes an HttpRequest object and a User object. 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.
Note that data set during the anonymous session is retained when the user logs in.
This example shows how you might use both authenticate() and 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.
Calling authenticate() first
When you’re manually logging a user in, you must call authenticate() before you call login(). authenticate() sets an attribute on the 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.
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 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.
Creates a hashed password in the format used by this application. It takes two arguments: hashing algorithm to use and the password in plain-text. Currently supported algorithms are: 'sha1', 'md5' and 'crypt' if you have the crypt library installed. If the second argument is None, an unusable password is returned (a one that will be never accepted by django.contrib.auth.hashers.check_password()).
Checks if the given string is a hashed password that has a chance of being verified against django.contrib.auth.hashers.check_password().
To log out a user who has been logged in via django.contrib.auth.login(), use django.contrib.auth.logout() within your view. It takes an 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 logout() doesn’t throw any errors if the user wasn’t logged in.
When you call 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 django.contrib.auth.logout().
The auth framework uses two signals that can be used for notification when a user logs in or out.
Sent when a user logs in successfully.
Arguments sent with this signal:
Sent when the logout method is called.
The simple, raw way to limit access to pages is to check request.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')
# ...
As a shortcut, you can use the convenient login_required() decorator:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
login_required() does the following:
By default, the path that the user should be redirected to upon successful authentication is stored in a query string parameter called "next". If you would prefer to use a different name for this parameter, login_required() takes an optional redirect_field_name parameter:
from django.contrib.auth.decorators import login_required
@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
...
Note that if you provide a value to redirect_field_name, you will most likely need to customize your login template as well, since the template context variable which stores the redirect path will use the value of redirect_field_name as its key rather than "next" (the default).
login_required() also takes an optional login_url parameter. Example:
from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
...
Note that if you don’t specify the login_url parameter, you’ll need to map the appropriate Django view to settings.LOGIN_URL. For example, using the defaults, add the following line to your URLconf:
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
URL name: login
See the URL documentation for details on using named URL patterns.
Here’s what django.contrib.auth.views.login does:
It’s your responsibility to provide the login form in a template called registration/login.html by default. This template gets passed four template context variables:
If you’d prefer not to call the template 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 myapp/login.html instead:
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),
You can also specify the name of the GET field which contains the URL to redirect to after login by passing redirect_field_name to the view. By default, the field is called next.
Here’s a sample registration/login.html template you can use as a starting point. It assumes you have a base.html template that defines a content block:
{% extends "base.html" %}
{% load url from future %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<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 %}
If you are using alternate authentication (see Other authentication sources) you can pass a custom authentication form to the login view via the authentication_form parameter. This form must accept a request keyword argument in its __init__ method, and provide a get_user method which returns the authenticated user object (this method is only ever called after successful form validation).
The login() view and the Other built-in views now all return a TemplateResponse instance, which allows you to easily customize the response data before rendering. For more details, see the TemplateResponse documentation.
In addition to the login() view, the authentication system includes a few other useful built-in views located in django.contrib.auth.views:
Logs a user out.
URL name: logout
See the URL documentation for details on using named URL patterns.
Optional arguments:
Template context:
Logs a user out, then redirects to the login page.
URL name: No default URL provided
Optional arguments:
Allows a user to change their password.
URL name: password_change
Optional arguments:
template_name: The full name of a template to use for displaying the password change form. Defaults to registration/password_change_form.html if not supplied.
post_change_redirect: The URL to redirect to after a successful password change.
password_change_form: A custom “change password” form which must accept a user keyword argument. The form is responsible for actually changing the user’s password. Defaults to PasswordChangeForm.
Template context:
The page shown after a user has changed their password.
URL name: password_change_done
Optional arguments:
Allows a user to reset their password by generating a one-time use link that can be used to reset the password, and sending that link to the user’s registered email address.
URL name: password_reset
Optional arguments:
template_name: The full name of a template to use for displaying the password reset form. Defaults to registration/password_reset_form.html if not supplied.
email_template_name: The full name of a template to use for generating the email with the new password. Defaults to registration/password_reset_email.html if not supplied.
subject_template_name: The full name of a template to use for the subject of the email with the new password. Defaults to registration/password_reset_subject.txt if not supplied.
password_reset_form: Form that will be used to set the password. Defaults to PasswordResetForm.
token_generator: Instance of the class to check the password. This will default to default_token_generator, it’s an instance of django.contrib.auth.tokens.PasswordResetTokenGenerator.
post_reset_redirect: The URL to redirect to after a successful password change.
from_email: A valid email address. By default Django uses the DEFAULT_FROM_EMAIL.
Template context:
Email template context:
Sample registration/password_reset_email.html (email body template):
{% load url from future %}
Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ site_name }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %}
The same template context is used for subject template. Subject must be single line plain text string.
The page shown after a user has been emailed a link to reset their password. This view is called by default if the password_reset() view doesn’t have an explicit post_reset_redirect URL set.
URL name: password_reset_done
Optional arguments:
Presents a form for entering a new password.
URL name: password_reset_confirm
Optional arguments:
Template context:
Presents a view which informs the user that the password has been successfully changed.
URL name: password_reset_complete
Optional arguments:
Redirects to the login page, and then back to another URL after a successful login.
Required arguments:
Optional arguments:
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 located in django.contrib.auth.forms:
A form used in the admin interface to change a user’s password.
A form for logging a user in.
A form for allowing a user to change their password.
A form for generating and emailing a one-time use link to reset a user’s password.
A form that lets a user change his/her password without entering the old password.
A form used in the admin interface to change a user’s information and permissions.
A form for creating a new user.
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 request.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.has_perm('polls.can_vote'):
return HttpResponse("You can't vote in this poll.")
# ...
As a shortcut, you can use the convenient user_passes_test decorator:
from django.contrib.auth.decorators import user_passes_test
@user_passes_test(lambda u: u.has_perm('polls.can_vote'))
def my_view(request):
...
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 permission_required() decorator, described later in this document.
user_passes_test() takes a required argument: a callable that takes a User object and returns True if the user is allowed to view the page. Note that user_passes_test() does not automatically check that the User is not anonymous.
user_passes_test() takes an optional login_url argument, which lets you specify the URL for your login page (settings.LOGIN_URL by default).
For example:
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):
...
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 permission_required() decorator. Using this decorator, the earlier example can be written as:
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote')
def my_view(request):
...
As for the User.has_perm() method, permission names take the form "<app label>.<permission codename>" (i.e. polls.can_vote for a permission on a model in the polls application).
Note that permission_required() also takes an optional login_url parameter. Example:
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
...
As in the login_required() decorator, login_url defaults to settings.LOGIN_URL.
Added raise_exception parameter. If given, the decorator will raise PermissionDenied, prompting the 403 (HTTP Forbidden) view instead of redirecting to the login page.
To limit access to a class-based generic view, decorate the View.dispatch method on the class. See Decorating the class for details.
To limit access to a function-based generic view, 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)
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:
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.
When django.contrib.auth is listed in your 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 manage.py syncdb; the first time you run syncdb after adding django.contrib.auth to 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 manage.py syncdb.
Assuming you have an application with an app_label foo and a model named Bar, to test for basic permissions you should use:
To create custom permissions for a given model object, use the permissions model Meta attribute.
This example Task model creates three custom permissions, i.e., actions users can or cannot do with Task instances, specific to your application:
class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
("change_task_status", "Can change the status of tasks"),
("close_task", "Can remove a task by setting its status as closed"),
)
The only thing this does is create those extra permissions when you run manage.py syncdb. Your code is in charge of checking the value of these permissions when an user is trying to access the functionality provided by the application (viewing tasks, changing the status of tasks, closing tasks.) Continuing the above example, the following checks if a user may view tasks:
user.has_perm('app.view_task')
Permission objects have the following fields:
Required. 50 characters or fewer. Example: 'Can vote'.
Required. A reference to the django_content_type database table, which contains a record for each installed Django model.
Required. 100 characters or fewer. Example: 'can_vote'.
Permission objects have the standard data-access methods like any other Django model.
While custom permissions can be defined within a model’s Meta class, you can also create permissions directly. For example, you can create the can_publish permission for a BlogPost model in myapp:
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get(app_label='myapp', model='BlogPost')
permission = Permission.objects.create(codename='can_publish',
name='Can Publish Posts',
content_type=content_type)
The permission can then be assigned to a User via its user_permissions attribute or to a Group via its permissions attribute.
The currently logged-in user and his/her permissions are made available in the template context when you use RequestContext.
Technicality
Technically, these variables are only made available in the template context if you use RequestContext and your TEMPLATE_CONTEXT_PROCESSORS setting contains "django.contrib.auth.context_processors.auth", which is default. For more, see the RequestContext docs.
When rendering a template RequestContext, the currently logged-in user, either a User instance or an 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 %}
This template context variable is not available if a RequestContext is not being used.
The currently logged-in user’s permissions are stored in the template variable {{ perms }}. This is an instance of django.contrib.auth.context_processors.PermWrapper, which is a template-friendly proxy of permissions.
In the {{ perms }} object, single-attribute lookup is a proxy to 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 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 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 email messages.
Group objects have the following fields:
Required. 80 characters or fewer. Any characters are permitted. Example: 'Awesome Users'.
Many-to-many field to Permissions:
group.permissions = [permission_list]
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()
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 other authentication sources. You can override Django’s default database-based scheme, or you can use the default system in tandem with other systems.
See the authentication backend reference for information on the authentication backends included with Django.
Behind the scenes, Django maintains a list of “authentication backends” that it checks for authentication. When somebody calls 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 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, 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 AUTHENTICATION_BACKENDS matters, so if the same username and password is valid in multiple backends, Django will stop processing at the first positive match.
Примечание
Once a user has authenticated, Django stores which backend was used to authenticate the user in the user’s session, and re-uses the same backend for the duration of that session whenever access to the currently authenticated user is needed. This effectively means that authentication sources are cached on a per-session basis, so if you change AUTHENTICATION_BACKENDS, you’ll need to clear out session data if you need to force users to re-authenticate using different methods. A simple way to do that is simply to execute Session.objects.all().delete().
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(object):
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(object):
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(object):
"""
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'
"""
supports_inactive_user = False
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
Custom auth backends can provide their own permissions.
The user model will delegate permission lookup functions (get_group_permissions(), get_all_permissions(), has_perm(), and 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(object):
# ...
def has_perm(self, user_obj, perm, obj=None):
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 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.
An anonymous user is one that is not authenticated i.e. they have provided no valid authentication details. However, that does not necessarily mean they are not authorized to do anything. At the most basic level, most Web sites authorize anonymous users to browse most of the site, and many allow anonymous posting of comments etc.
Django’s permission framework does not have a place to store permissions for anonymous users. However, it has a foundation that allows custom authentication backends to specify authorization for anonymous users. This is especially useful for the authors of re-usable apps, who can delegate all questions of authorization to the auth backend, rather than needing settings, for example, to control anonymous access.
An inactive user is a one that is authenticated but has its attribute is_active set to False. However this does not mean they are not authorized to do anything. For example they are allowed to activate their account.
The support for anonymous users in the permission system allows for anonymous users to have permissions to do something while inactive authenticated users do not.
To enable this on your own backend, you must set the class attribute supports_inactive_user to True.
A nonexisting supports_inactive_user attribute will raise a PendingDeprecationWarning if used in Django 1.3. In Django 1.4, this warning will be updated to a DeprecationWarning which will be displayed loudly. Additionally supports_inactive_user will be set to False. Django 1.5 will assume that every backend supports inactive users being passed to the authorization methods.
Django’s permission framework has a foundation for object permissions, though there is no implementation for it in the core. That means that checking for object permissions will always return False or an empty list (depending on the check performed).
Mar 30, 2016