Spec-Zone.ru › Django 2.1

Использование системы аутентификации Django

В данном документе объясняется использование системы аутентификации Django по умолчанию. Эта конфигурация эволюционировала для удовлетворения наиболее распространённых потребностей проектов, обработки широкого спектра задач и имеет продуманную реализацию управления паролями и разрешениями. Для проектов, где потребности в аутентификации отличаются от стандартных, Django поддерживает расширенную настройку и расширение системы аутентификации.

Система аутентификации Django обеспечивает как аутентификацию, так и авторизацию вместе, и обычно называется системой аутентификации, поскольку эти функции взаимосвязаны.

User объекты

User объекты являются основой системы аутентификации. Они обычно представляют людей, взаимодействующих с вашим сайтом, и используются для таких задач, как ограничение доступа, регистрация пользовательских профилей, привязка контента к создателям и т. д. В рамках фреймворка аутентификации Django существует только один класс пользователей, т.е. 'superusers' или администраторские 'staff' пользователи — это просто пользовательские объекты со специальными атрибутами, а не отдельные классы пользователей.

Основные атрибуты стандартного пользователя:

  • username
  • password
  • email
  • first_name
  • last_name

См. полную справку по full API documentation, данное ниже описание носит более прикладной характер.

Создание пользователей

Самый прямой способ создания пользователей — использование встроенной функции 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.last_name = 'Lennon'
>>> user.save()

Если у вас установлен Django admin, вы также можете создать пользователей интерактивно.

Создание суперпользователей

Создайте суперпользователей, используя команду createsuperuser:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

Вам будет предложено ввести пароль. После ввода пароль будет создан сразу. Если вы опустите опцию --username или --email, вам будет предложено ввести эти значения.

Изменение паролей

Django не хранит исходные (в виде обычного текста) пароли в модели пользователя, а только хэш (см. документацию по управлению паролями для получения полной информации). По этой причине не пытайтесь напрямую манипулировать атрибутом пароля пользователя. Именно поэтому для создания пользователя используется вспомогательная функция.

Чтобы изменить пароль пользователя, у вас есть несколько вариантов:

manage.py changepassword *username* предлагает способ изменения пароля пользователя из командной строки. Вам будет предложено изменить пароль заданного пользователя, который вы должны ввести дважды. Если они совпадут, новый пароль будет изменён немедленно. Если вы не укажете пользователя, команда попытается изменить пароль пользователя, имя которого соответствует текущему системному пользователю.

Вы также можете изменить пароль программно, используя set_password():

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()

Если у вас установлен Django admin, вы также можете изменить пароли пользователей на страницах административной панели системы аутентификации системы аутентификации.

Django также предоставляет представления и формы, которые могут быть использованы для того, чтобы пользователи могли сами менять свои пароли.

Изменение пароля пользователя приведет к выходу всех его сессий. Подробности см. в разделе Недействительность сессий при изменении пароля.

Аутентификация пользователей

authenticate(request=None, **credentials) [source]

Используйте authenticate() для проверки набора учетных данных. Он принимает учетные данные в качестве ключевых аргументов, username и password в случае по умолчанию, сравнивает их с каждым обработчиком аутентификации и возвращает объект User, если учетные данные действительны для обработчика. Если учетные данные не действительны для любого обработчика, или если обработчик вызывает PermissionDenied, он возвращает None. Например:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials

request — необъект HttpRequest, который передается в метод authenticate() обработчиков аутентификации.

Примечание

Это низкоуровневый способ аутентификации набора учетных данных; например, он используется RemoteUserMiddleware. Если вы не создаёте собственную систему аутентификации, вы, вероятно, не будете использовать её. Вместо этого, если вам нужен способ входа пользователя, воспользуйтесь LoginView.

Разрешения и авторизация

Django поставляется с простой системой разрешений. Она предоставляет способ назначения разрешений определённым пользователям и группам пользователей.

Она используется в Django admin, но вы можете использовать её и в собственном коде.

Django admin использует разрешения следующим образом:

  • Доступ к просмотру объектов ограничен пользователями с разрешением «просмотр» или «изменение» для данного типа объектов.
  • Доступ к форме «добавления» и добавлению объекта ограничен пользователями с разрешением «добавление» для данного типа объектов.
  • Доступ к просмотру списка изменений, просмотру формы «изменение» и изменению объекта ограничен пользователями с разрешением «изменение» для данного типа объектов.
  • Доступ к удалению объекта ограничен пользователями с разрешением «удаление» для данного типа объектов.

Разрешения могут быть заданы не только по типу объекта, но и по конкретному экземпляру объекта. Используя методы has_view_permission(), has_add_permission(), has_change_permission() и has_delete_permission(), предоставляемые классом ModelAdmin, можно настроить разрешения для различных экземпляров объектов одного типа.

User объекты имеют два поля many-to-many: groups и user_permissions. User объекты могут обращаться к связанным объектам так же, как и любой другой модель Django:

myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

Стандартные разрешения

Когда django.contrib.auth указан в настройке INSTALLED_APPS, это гарантирует, что четыре стандартных разрешения — добавление, изменение, удаление и просмотр — создаются для каждой модели Django, определённой в одном из установленных приложений.

Эти разрешения будут созданы при выполнении manage.py migrate; при первом запуске migrate после добавления django.contrib.auth в INSTALLED_APPS, стандартные разрешения будут созданы для всех ранее установленных моделей, а также для любых новых моделей, устанавливаемых в это время. После этого он будет создавать стандартные разрешения для новых моделей каждый раз, когда вы запускаете manage.py migrate (функция, которая создаёт разрешения, связана со сигналом post_migrate).

Предполагая, что у вас есть приложение с app_label foo и моделью под названием Bar, для проверки основных разрешений следует использовать:

  • добавить: user.has_perm('foo.add_bar')
  • изменить: user.has_perm('foo.change_bar')
  • удалить: user.has_perm('foo.delete_bar')
  • просмотреть: user.has_perm('foo.view_bar')

Модель Permission редко используется напрямую.

Группы

Модели django.contrib.auth.models.Group являются универсальным способом категоризации пользователей, позволяющим применять разрешения или какие-либо другие метки к этим пользователям. Пользователь может принадлежать к любому количеству групп.

Пользователь в группе автоматически обладает разрешениями, предоставленными этой группе. Например, если группа Site editors имеет разрешение can_edit_home_page, любой пользователь в этой группе также будет обладать этим разрешением.

Помимо разрешений, группы являются удобным способом категоризации пользователей для присвоения им меток или расширенных функций. Например, вы можете создать группу 'Special users', и вы можете написать код, который, скажем, предоставит им доступ к закрытой части вашего сайта или отправит им закрытые сообщения электронной почты.

Программное создание разрешений

Хотя настраиваемые разрешения могут быть определены внутри класса Meta модели, вы также можете создавать разрешения напрямую. Например, вы можете создать разрешение can_publish для модели BlogPost в myapp:

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

Затем разрешение можно назначить пользователю User через его атрибут user_permissions или группе Group через её атрибут permissions.

Кэширование разрешений

Backend ModelBackend кэширует разрешения в объекте пользователя после первого запроса на их получение для проверки разрешений. Это обычно не вызывает проблем в цикле запроса-ответа, поскольку разрешения обычно не проверяются сразу после добавления (например, в админке). Если вы добавляете разрешения и проверяете их сразу после этого, например, в тесте или представлении, то проще всего переполучить пользователя из базы данных. Например:

from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from myapp.models import BlogPost

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_blogpost')

    content_type = ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.get(
        codename='change_blogpost',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_blogpost')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_blogpost')  # True

    ...

Авторизация в веб-запросах

Django использует сессии и middleware для интеграции системы аутентификации с request objects.

Они предоставляют атрибут request.user в каждом запросе, представляющий текущего пользователя. Если текущий пользователь не авторизован, этот атрибут будет устанавливаться в экземпляр AnonymousUser, в противном случае - в экземпляр User.

Вы можете их различать с помощью is_authenticated, например:

if request.user.is_authenticated:
    # Do something for authenticated users.
    ...
else:
    # Do something for anonymous users.
    ...

Как войти в систему

Если у вас есть авторизованный пользователь, которого вы хотите прикрепить к текущей сессии, это делается с помощью функции login().

login(request, user, backend=None) [source]

Чтобы войти в систему, из представления, используйте login(). Она принимает объект HttpRequest и объект User. login() сохраняет ID пользователя в сессии, используя фреймворк сессий Django.

Обратите внимание, что любые данные, установленные во время анонимной сессии, сохраняются в сессии после входа пользователя.

Этот пример показывает, как вы можете использовать как authenticate(), так и login():

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        # Redirect to a success page.
        ...
    else:
        # Return an 'invalid login' error message.
        ...

Выбор бэкенда аутентификации

Когда пользователь входит в систему, ID пользователя и бэкенд, который использовался для аутентификации, сохраняются в сессии пользователя. Это позволяет одному и тому же бэкенду аутентификации получать данные пользователя при последующих запросах. Бэкенд аутентификации для сохранения в сессии выбирается следующим образом:

  1. Используйте значение необязательного аргумента backend, если он указан.
  2. Используйте значение атрибута user.backend, если он присутствует. Это позволяет сопоставить authenticate() и login(): authenticate() устанавливает атрибут user.backend в объекте возвращаемого пользователя.
  3. Используйте значение backend в AUTHENTICATION_BACKENDS, если оно единственное.
  4. В противном случае, вызовите исключение.

В случаях 1 и 2 значение аргумента backend или атрибута user.backend должно быть строкой импорта с точкой (как в AUTHENTICATION_BACKENDS), а не самим классом бэкенда.

Как выйти из системы

logout(request) [source]

Чтобы выйти из системы пользователя, авторизованного с помощью django.contrib.auth.login(), используйте django.contrib.auth.logout() в своём представлении. Она принимает объект HttpRequest и не имеет возвращаемого значения. Пример:

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

Обратите внимание, что logout() не генерирует никаких ошибок, если пользователь не был авторизован.

Когда вы вызываете logout(), данные сессии для текущего запроса полностью очищаются. Все существующие данные удаляются. Это предотвращает использование одним и тем же веб-браузером другим человеком для входа в систему и доступа к данным сессии предыдущего пользователя. Если вы хотите поместить что-либо в сессию, которое будет доступно пользователю сразу после выхода, сделайте это *после* вызова django.contrib.auth.logout().

Ограничение доступа для авторизованных пользователей

Прямой способ

Простой и прямой способ ограничить доступ к страницам заключается в проверке request.user.is_authenticated и либо перенаправлении на страницу входа:

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...

…или отображении сообщения об ошибке:

from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated:
        return render(request, 'myapp/login_error.html')
    # ...

Декоратор login_required

login_required(redirect_field_name='next', login_url=None) [source]

В качестве сокращения можно использовать удобный декоратор login_required():

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

login_required() выполняет следующие действия:

  • Если пользователь не авторизован, перенаправить его на settings.LOGIN_URL, передавая текущий абсолютный путь в параметре запроса. Пример: /accounts/login/?next=/polls/3/.
  • Если пользователь авторизован, выполнить представление обычно. Код представления может свободно предполагать, что пользователь авторизован.

По умолчанию путь, на который пользователь должен быть перенаправлен после успешной аутентификации, хранится в параметре запроса, называемом "next". Если вы предпочитаете использовать другое имя для этого параметра, login_required() принимает необязательный параметр redirect_field_name.

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

Обратите внимание, что если вы укажете значение для redirect_field_name, вам, скорее всего, также потребуется настроить вашу шаблонную разметку входа в систему, так как переменная контекста шаблона, хранящая путь перенаправления, будет использовать значение redirect_field_name в качестве своего ключа вместо "next" (по умолчанию).

login_required() также принимает необязательный параметр login_url. Пример:

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

Обратите внимание, что если вы не укажете параметр login_url, вам необходимо убедиться, что settings.LOGIN_URL и ваше представление входа в систему правильно связаны. Например, используя значения по умолчанию, добавьте следующие строки в свой файл URL:

from django.contrib.auth import views as auth_views

path('accounts/login/', auth_views.LoginView.as_view()),

settings.LOGIN_URL также принимает имена функций представлений и именованные шаблоны URL. Это позволяет вам свободно переопределять представление входа в систему в вашем файле URL без необходимости обновления настройки.

Примечание

Декоратор login_required НЕ проверяет флаг is_active пользователя, но стандартный AUTHENTICATION_BACKENDS отклоняет неактивных пользователей.

См. также

Если вы пишете пользовательские представления для администрирования Django (или вам нужна та же проверка авторизации, что и у встроенных представлений), вы можете найти декоратор django.contrib.admin.views.decorators.staff_member_required() полезной альтернативой декоратору login_required().

Миксин LoginRequired

При использовании представлений на основе классов вы можете достичь того же результата, что и с login_required, используя миксин LoginRequiredMixin. Этот миксин должен стоять в левой позиции в списке наследования.

class LoginRequiredMixin

Если представление использует этот миксин, все запросы от неавторизованных пользователей будут перенаправлены на страницу входа или отобразят ошибку HTTP 403 Forbidden, в зависимости от параметра raise_exception.

Вы можете установить любой из параметров AccessMixin для настройки обработки неавторизованных пользователей:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Примечание

Так же, как и декоратор login_required, этот миксин НЕ проверяет флаг is_active пользователя, но по умолчанию AUTHENTICATION_BACKENDS отклоняет неактивных пользователей.

Ограничение доступа для авторизованных пользователей, прошедших тест

Чтобы ограничить доступ на основе определенных разрешений или другого теста, вы сделаете в основном то же самое, что описано в предыдущем разделе.

Простой способ — выполнить ваш тест на request.user непосредственно в представлении. Например, это представление проверяет, имеет ли пользователь электронную почту в нужном домене, и если нет, перенаправляет на страницу входа:

from django.shortcuts import redirect

def my_view(request):
    if not request.user.email.endswith('@example.com'):
        return redirect('/login/?next=%s' % request.path)
    # ...
user_passes_test(test_func, login_url=None, redirect_field_name='next') [source]

В качестве сокращения можно использовать удобный декоратор user_passes_test, который выполняет перенаправление, когда вызываемый объект возвращает False:

from django.contrib.auth.decorators import user_passes_test

def email_check(user):
    return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
    ...

user_passes_test() принимает обязательный аргумент: вызываемый объект, который принимает объект User и возвращает True , если пользователю разрешено просматривать страницу. Обратите внимание, что user_passes_test() не проверяет автоматически, что User не анонимный.

user_passes_test() принимает два необязательных аргумента:

login_url
Позволяет указать URL, на который будут перенаправлены пользователи, которые не прошли проверку. Это может быть страница входа и по умолчанию устанавливается как settings.LOGIN_URL, если вы не укажете другое.
redirect_field_name
Так же, как и для login_required(). Установка в None удаляет его из URL, что может быть необходимо, если вы перенаправляете пользователей, которые не прошли проверку, на страницу, не являющуюся страницей входа, где нет параметра «следующая страница».

Например:

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
    ...
class UserPassesTestMixin

При использовании представлений на основе классов вы можете использовать UserPassesTestMixin для этого.

test_func()

Вы должны переопределить метод test_func() класса, чтобы предоставить тест, который будет выполняться. Кроме того, вы можете установить любой из параметров AccessMixin для настройки обработки неавторизованных пользователей:

from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.email.endswith('@example.com')
get_test_func()

Вы также можете переопределить метод get_test_func() , чтобы миксин использовал функцию с другим именем для проверок (вместо test_func()).

Утилизация UserPassesTestMixin

Из-за способа реализации UserPassesTestMixin вы не можете использовать их в списке наследования. Следующее НЕ работает:

class TestMixin1(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.email.endswith('@example.com')

class TestMixin2(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.username.startswith('django')

class MyView(TestMixin1, TestMixin2, View):
    ...

Если бы TestMixin1 вызывал super() и учитывал этот результат, TestMixin1 больше не работал бы автономно.

Декоратор permission_required

permission_required(perm, login_url=None, raise_exception=False) [source]

Это относительно распространённая задача — проверить, обладает ли пользователь определённым разрешением. По этой причине Django предоставляет для этого сокращение: декоратор permission_required().

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...

Как и метод has_perm(), имена разрешений имеют вид "<app label>.<permission codename>" (например, polls.can_vote для разрешения на модель в приложении polls).

Декоратор также может принимать итерируемый список разрешений, в этом случае пользователь должен обладать всеми указанными разрешениями, чтобы получить доступ к представлению.

Обратите внимание, что permission_required() также принимает необязательный параметр login_url:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...

Как и в декораторе login_required(), параметр login_url по умолчанию равен settings.LOGIN_URL.

Если параметр raise_exception указан, декоратор вызовет исключение PermissionDenied, что вызовет отображение страницы 403 (HTTP Запрещено), вместо перенаправления на страницу входа в систему.

Если вы хотите использовать raise_exception и предоставить пользователям возможность сначала авторизоваться, вы можете добавить декоратор login_required():

from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('polls.can_vote', raise_exception=True)
def my_view(request):
    ...

Это также предотвращает цикл перенаправления, когда функция LoginView’s redirect_authenticated_user=True и авторизованный пользователь не обладает всеми необходимыми разрешениями.

Миксин PermissionRequiredMixin

Для применения проверок разрешений к представлениям на основе классов, вы можете использовать PermissionRequiredMixin:

class PermissionRequiredMixin

Этот миксин, как и декоратор permission_required , проверяет, обладает ли пользователь, обращающийся к представлению, всеми указанными разрешениями. Вы должны указать разрешение (или итерируемый список разрешений) с помощью параметра permission_required:

from django.contrib.auth.mixins import PermissionRequiredMixin

class MyView(PermissionRequiredMixin, View):
    permission_required = 'polls.can_vote'
    # Or multiple of permissions:
    permission_required = ('polls.can_open', 'polls.can_edit')

Вы можете установить любые параметры миксина AccessMixin, чтобы настроить обработку пользователей без доступа.

Вы также можете переопределить следующие методы:

get_permission_required()

Возвращает итерируемый список имён разрешений, используемых миксином. По умолчанию возвращает значение атрибута permission_required , преобразованное в кортеж при необходимости.

has_permission()

Возвращает булево значение, обозначающее, обладает ли текущий пользователь разрешением на выполнение декорированного представления. По умолчанию это возвращает результат вызова has_perms() со списком разрешений, возвращаемым методом get_permission_required().

Перенаправление запросов без доступа в представлениях на основе классов

Для облегчения обработки ограничений доступа в представлениях на основе классов, миксин AccessMixin может быть использован для настройки поведения представления при отказе в доступе. Авторизованным пользователям отказывается доступ с HTTP-ответом 403 Запрещено. Анонимные пользователи перенаправляются на страницу входа в систему или отображается HTTP-ответ 403 Запрещено, в зависимости от атрибута raise_exception.

Изменено в Django 2.1:

В более ранних версиях, авторизованные пользователи, которые не имели разрешений, перенаправлялись на страницу входа в систему (что приводило к циклу), вместо получения HTTP-ответа 403 Запрещено.

class AccessMixin
login_url

Значение по умолчанию для get_login_url(). По умолчанию равно None, в этом случае get_login_url() обращается к settings.LOGIN_URL.

permission_denied_message

Значение по умолчанию для get_permission_denied_message(). По умолчанию пустая строка.

redirect_field_name

Значение по умолчанию для get_redirect_field_name(). По умолчанию равно "next".

raise_exception

Если этот атрибут установлен в значение True, исключение PermissionDenied генерируется, когда условия не соблюдены. Когда значение равно False (значение по умолчанию), анонимные пользователи перенаправляются на страницу входа в систему.

get_login_url()

Возвращает URL, на который будут перенаправлены пользователи, не прошедшие проверку. Возвращает login_url, если оно установлено, или settings.LOGIN_URL в противном случае.

get_permission_denied_message()

Когда raise_exception равно True, этот метод может использоваться для управления сообщением об ошибке, передаваемым обработчику ошибок для отображения пользователю. По умолчанию возвращает атрибут permission_denied_message.

get_redirect_field_name()

Возвращает имя параметра запроса, который будет содержать URL, на который пользователь будет перенаправлен после успешного входа в систему. Если вы установите его в None, параметр запроса не будет добавлен. По умолчанию возвращает атрибут redirect_field_name.

handle_no_permission()

В зависимости от значения raise_exception, метод либо генерирует исключение PermissionDenied, либо перенаправляет пользователя на login_url, при необходимости включая redirect_field_name.

Отключение сессии при изменении пароля

Если ваша модель пользователя AUTH_USER_MODEL наследуется от AbstractBaseUser или реализует свой собственный метод get_session_auth_hash(), авторизованные сессии будут включать хэш, возвращаемый этой функцией. В случае с AbstractBaseUser, это HMAC поля пароля. Django проверяет, что хэш в сессии для каждого запроса совпадает с хэшем, вычисленным во время запроса. Это позволяет пользователю выйти из всех своих сессий, изменив пароль.

END_OF_DOCUMENT_MARKER

Встроенные в Django представления для изменения пароля, PasswordChangeView и представление user_change_password в админском интерфейсе django.contrib.auth, обновляют сеанс с новым хешем пароля, чтобы пользователь, меняющий свой пароль, не был выведен из системы. Если у вас есть пользовательское представление для изменения пароля и вы хотите получить подобное поведение, используйте функцию update_session_auth_hash().

update_session_auth_hash(request, user) [source]

Эта функция принимает текущий запрос и обновлённый объект пользователя, из которого будет получен новый хеш сессии, и обновляет хеш сессии соответствующим образом. Она также меняет ключ сессии, чтобы украденный куки сессии стал недействительным.

Пример использования:

from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...

Примечание

Поскольку get_session_auth_hash() основана на SECRET_KEY, обновление сайта с использованием нового секрета сделает все существующие сессии недействительными.

Представления аутентификации

Django предоставляет несколько представлений, которые можно использовать для обработки входа в систему, выхода из системы и управления паролями. Они используют стандартные формы аутентификации, но вы также можете передавать свои собственные формы.

Django не предоставляет по умолчанию шаблоны для представлений аутентификации. Вы должны создать свои собственные шаблоны для используемых представлений. Контекст шаблона документирован в каждом представлении, см. Все представления аутентификации.

Использование представлений

Существует несколько способов реализовать эти представления в вашем проекте. Самый простой способ — включить предоставленный URLconf в django.contrib.auth.urls в вашем собственном URLconf, например:

urlpatterns = [
    path('accounts/', include('django.contrib.auth.urls')),
]

Это включит следующие URL-шаблоны:

accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']

Представления предоставляют имя URL для более удобной ссылки. Подробнее об использовании именованных URL-шаблонов см. в документации по URL.

Если вы хотите больше контроля над своими URL, вы можете сослаться на конкретное представление в вашем URLconf:

from django.contrib.auth import views as auth_views

urlpatterns = [
    path('change-password/', auth_views.PasswordChangeView.as_view()),
]

Представления имеют необязательные аргументы, которые вы можете использовать для изменения поведения представления. Например, если вы хотите изменить имя шаблона, используемого представлением, вы можете предоставить аргумент template_name. Способ сделать это — предоставить ключевые аргументы в URLconf, они будут переданы в представление. Например:

urlpatterns = [
    path(
        'change-password/',
        auth_views.PasswordChangeView.as_view(template_name='change-password.html'),
    ),
]

Все представления являются базирующимися на классах, что позволяет легко настраивать их, наследовав их.

Все представления аутентификации

Вот список всех представлений, которые предоставляет django.contrib.auth. Подробности реализации см. в Использование представлений.

class LoginView

Имя URL: login

Подробности об использовании именованных URL-шаблонов см. в документации по URL.

Атрибуты:

  • template_name: Имя шаблона для отображения представления, используемого для входа в систему. По умолчанию registration/login.html.
  • redirect_field_name: Имя поля GET, содержащего URL для перенаправления после входа. По умолчанию next.
  • authentication_form: Вызываемый объект (обычно просто класс формы) для аутентификации. По умолчанию AuthenticationForm.
  • extra_context: Словарь данных контекста, которые будут добавлены к стандартным данным контекста, передаваемым шаблону.
  • redirect_authenticated_user: Булево значение, определяющее, будут ли аутентифицированные пользователи, посещающие страницу входа, перенаправлены так, как будто они только что успешно вошли в систему. По умолчанию False.

    Предупреждение

    Если вы включите redirect_authenticated_user, другие сайты смогут определить, авторизованы ли их посетители на вашем сайте, запросив URL-адреса перенаправления к файлам изображений на вашем сайте. Чтобы избежать утечки информации о «отпечатках социальных сетей», размещайте все изображения и значок сайта на отдельном домене.

    Включение redirect_authenticated_user также может привести к циклу перенаправления при использовании декоратора permission_required(), если параметр raise_exception не используется.

  • success_url_allowed_hosts: set хостов, помимо request.get_host(), которые безопасны для перенаправления после входа. По умолчанию пустой set.

Вот что делает LoginView:

  • Если вызывается через GET, отображается форма входа, которая отправляет POST-запрос на тот же URL. Подробнее об этом чуть позже.
  • Если вызывается через POST с предоставленными пользователем учетными данными, он пытается войти в систему. Если вход успешен, представление перенаправляет на URL, указанный в next. Если next не указан, он перенаправляется на settings.LOGIN_REDIRECT_URL (который по умолчанию равен /accounts/profile/). Если вход не успешен, отображается форма входа.

Вам необходимо предоставить html для шаблона входа, по умолчанию называемого registration/login.html. Этот шаблон получает четыре переменные контекста шаблона:

  • form: Объект Form, представляющий AuthenticationForm.
  • next: URL для перенаправления после успешного входа. Он может также содержать строку запроса.
  • site: Текущий Site в соответствии с настройкой SITE_ID. Если модуль сайтов не установлен, он будет настроен на экземпляр RequestSite, который определяет имя и домен сайта на основе текущего HttpRequest.
  • site_name: Псевдоним для site.name. Если модуль сайтов не установлен, он будет установлен в значение request.META['SERVER_NAME']. Для получения более подробной информации о сайтах, см. модуль «сайты».

Если вы предпочитаете не вызывать шаблон registration/login.html, вы можете передать параметр template_name через дополнительные аргументы к методу as_view в вашем URLconf. Например, эта строка URLconf будет использовать myapp/login.html:

path('accounts/login/', auth_views.LoginView.as_view(template_name='myapp/login.html')),

Вы также можете указать имя поля GET, содержащего URL для перенаправления после входа, используя redirect_field_name. По умолчанию поле называется next.

Вот пример шаблона registration/login.html шаблона, который вы можете использовать в качестве отправной точки. Он предполагает, что у вас есть шаблон base.html, который определяет блок content:

{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

{% if next %}
    {% if user.is_authenticated %}
    <p>Your account doesn't have access to this page. To proceed,
    please login with an account that has access.</p>
    {% else %}
    <p>Please login to see this page.</p>
    {% endif %}
{% endif %}

<form method="post" action="{% url '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>

{# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>

{% endblock %}

Если у вас настроенная аутентификация (см. Настройка аутентификации), вы можете использовать пользовательскую форму аутентификации, задав атрибут authentication_form. Эта форма должна принимать аргумент request в своём методе __init__() и предоставлять метод get_user(), который возвращает объект аутентифицированного пользователя (этот метод вызывается только после успешной проверки формы).

class LogoutView

Выводит пользователя из системы.

Имя URL: logout

Атрибуты:

  • next_page: URL перенаправления после выхода. По умолчанию settings.LOGOUT_REDIRECT_URL.
  • template_name: Полное имя шаблона для отображения после выхода из системы. По умолчанию registration/logged_out.html.
  • redirect_field_name: Имя поля GET содержащего URL перенаправления после выхода. По умолчанию next. Переопределяет URL next_page если передан параметр GET.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
  • success_url_allowed_hosts: set хостов, помимо request.get_host(), которые безопасны для перенаправления после выхода. По умолчанию пустой set.

Контекст шаблона:

  • title: Строка «Выход», локализованная.
  • site: Текущий Site, в соответствии с настройкой SITE_ID. Если модуль сайтов не установлен, это будет экземпляр RequestSite, который получает имя сайта и домен из текущего HttpRequest.
  • site_name: Псевдоним для site.name. Если модуль сайтов не установлен, это будет значение request.META['SERVER_NAME']. Для получения более подробной информации о сайтах, смотрите Модуль «сайты».
logout_then_login(request, login_url=None)

Выводит пользователя из системы, затем перенаправляет на страницу входа.

Имя URL: Нет предоставленного по умолчанию URL

Дополнительные аргументы:

  • login_url: URL страницы входа для перенаправления. По умолчанию settings.LOGIN_URL, если не указано.
class PasswordChangeView

Имя URL: password_change

Позволяет пользователю изменить свой пароль.

Атрибуты:

  • template_name: Полное имя шаблона для отображения формы изменения пароля. По умолчанию registration/password_change_form.html если не указано.
  • success_url: URL для перенаправления после успешной смены пароля.
  • form_class: Пользовательская форма «смены пароля», которая должна принимать ключевой аргумент user. Форма отвечает за фактическое изменение пароля пользователя. По умолчанию PasswordChangeForm.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.

Контекст шаблона:

  • form: Форма изменения пароля (см. form_class выше).
class PasswordChangeDoneView

Имя URL: password_change_done

Страница, отображаемая после изменения пароля пользователем.

Атрибуты:

  • template_name: Полное имя шаблона для использования. По умолчанию registration/password_change_done.html если не указано.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
class PasswordResetView

Имя URL: password_reset

Позволяет пользователю сбросить пароль, сгенерировав одноразовую ссылку для сброса пароля и отправив её на зарегистрированный адрес электронной почты.

Если предоставленный адрес электронной почты не существует в системе, этот вид не отправит письмо, но пользователю также не будет показано сообщение об ошибке. Это предотвращает утечку информации потенциальным злоумышленникам. Если вы хотите вывести сообщение об ошибке в этом случае, можно создать подкласс PasswordResetForm и использовать атрибут form_class.

Пользователи, у которых установлен неиспользуемый пароль (см. set_unusable_password()), не могут запросить сброс пароля, чтобы предотвратить злоупотребление при использовании внешнего источника аутентификации, например, LDAP. Обратите внимание, что им не будет показано никакого сообщения об ошибке, так как это раскрыло бы существование их аккаунта, но письмо также не будет отправлено.

Атрибуты:

  • template_name: Полное имя шаблона для отображения формы сброса пароля. По умолчанию registration/password_reset_form.html если не указано.
  • form_class: Форма, которая будет использоваться для получения адреса электронной почты пользователя для сброса пароля. По умолчанию PasswordResetForm.
  • email_template_name: Полное имя шаблона для создания письма со ссылкой на сброс пароля. По умолчанию registration/password_reset_email.html если не указано.
  • subject_template_name: Полное имя шаблона для темы письма со ссылкой на сброс пароля. По умолчанию registration/password_reset_subject.txt если не указано.
  • token_generator: Экземпляр класса для проверки одноразовой ссылки. По умолчанию default_token_generator, это экземпляр django.contrib.auth.tokens.PasswordResetTokenGenerator.
  • success_url: URL для перенаправления после успешного запроса на сброс пароля.
  • from_email: Действительный адрес электронной почты. По умолчанию Django использует DEFAULT_FROM_EMAIL.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
  • html_email_template_name: Полное имя шаблона для создания multipart-письма с ссылкой на сброс пароля. По умолчанию HTML-письмо не отправляется.
  • extra_email_context: Словарь данных контекста, доступный в шаблоне письма.

Контекст шаблона:

  • form: Форма (см. form_class выше) для сброса пароля пользователя.

Контекст шаблона письма:

  • email: Псевдоним для user.email
  • user: Текущий User, в соответствии с полем формы email. Только активные пользователи могут сбросить пароль (User.is_active is True).
  • site_name: Псевдоним для site.name. Если модуль сайтов не установлен, это будет значение request.META['SERVER_NAME']. Для получения более подробной информации о сайтах, смотрите Модуль «сайты».
  • domain: Псевдоним для site.domain. Если модуль сайтов не установлен, это будет значение request.get_host().
  • protocol: http или https
  • uid: Первичный ключ пользователя, закодированный в base 64.
  • token: Токен для проверки валидности ссылки на сброс пароля.

Пример registration/password_reset_email.html (шаблон тела письма):

Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

Тот же контекст шаблона используется для шаблона темы. Тема должна быть строкой простого текста одной строкой.

class PasswordResetDoneView

Имя URL: password_reset_done

Страница, отображаемая после отправки пользователю ссылки на сброс пароля. Этот вид используется по умолчанию, если у PasswordResetView нет явным образом заданного success_url URL.

Примечание

Если предоставленный адрес электронной почты не существует в системе, пользователь неактивен или у него неиспользуемый пароль, пользователь всё равно будет перенаправлен на этот вид, но письмо не будет отправлено.

Атрибуты:

  • template_name: Полное имя шаблона для использования. По умолчанию registration/password_reset_done.html если не указано.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
class PasswordResetConfirmView

Имя URL: password_reset_confirm

Отображает форму для ввода нового пароля.

Аргументы ключевых слов из URL:

  • uidb64: Идентификатор пользователя, закодированный в base 64.
  • token: Токен для проверки валидности пароля.

Атрибуты:

  • template_name: Полное имя шаблона для отображения представления подтверждения пароля. Значение по умолчанию — registration/password_reset_confirm.html.
  • token_generator: Экземпляр класса для проверки пароля. По умолчанию — default_token_generator, экземпляр класса django.contrib.auth.tokens.PasswordResetTokenGenerator.
  • post_reset_login: Логическое значение, указывающее, следует ли автоматически аутентифицировать пользователя после успешной смены пароля. По умолчанию — False.
  • post_reset_login_backend: Точка доступа к аутентификационному бэкэнду, который следует использовать при аутентификации пользователя, если post_reset_login равно True. Требуется только при наличии нескольких настроек AUTHENTICATION_BACKENDS. Значение по умолчанию — None.
  • form_class: Форма, которая будет использоваться для установки пароля. По умолчанию — SetPasswordForm.
  • success_url: URL для перенаправления после смены пароля. По умолчанию — 'password_reset_complete'.
  • extra_context: Словарь данных контекста, которые будут добавлены к стандартным данным контекста, передаваемым шаблону.

Контекст шаблона:

  • form: Форма (см. form_class выше) для установки нового пароля пользователя.
  • validlink: Логическое значение, True, если ссылка (комбинация uidb64 и token ) является валидной или ещё не используется.
class PasswordResetCompleteView

Имя URL: password_reset_complete

Отображает представление, информирующее пользователя об успешной смене пароля.

Атрибуты:

  • template_name: Полное имя шаблона для отображения представления. По умолчанию — registration/password_reset_complete.html.
  • extra_context: Словарь данных контекста, которые будут добавлены к стандартным данным контекста, передаваемым шаблону.

Вспомогательные функции

redirect_to_login(next, login_url=None, redirect_field_name='next')

Перенаправляет на страницу входа и затем на другой URL после успешной авторизации.

Обязательные аргументы:

  • next: URL, на который следует перенаправить после успешной авторизации.

Необязательные аргументы:

  • login_url: URL страницы входа, на которую следует перенаправить. По умолчанию — settings.LOGIN_URL, если не указан.
  • redirect_field_name: Имя поля GET, содержащего URL для перенаправления после выхода. Переопределяет next, если указан аргумент GET.

Встроенные формы

Если вы не хотите использовать встроенные представления, но хотите воспользоваться удобством, не создавая формы для этой функциональности, система аутентификации предоставляет несколько встроенных форм, расположенных в django.contrib.auth.forms:

Примечание

Встроенные формы аутентификации делают определённые предположения относительно модели пользователя, с которой они работают. Если вы используете пользовательскую модель, может потребоваться определить собственные формы для системы аутентификации. Для получения дополнительной информации см. документацию по использованию встроенных форм аутентификации с пользовательскими моделями.

class AdminPasswordChangeForm

Форма, используемая в админском интерфейсе для смены пароля пользователя.

Принимает user в качестве первого позиционного аргумента.

class AuthenticationForm

Форма для входа пользователя.

Принимает request в качестве первого позиционного аргумента, который хранится в экземпляре формы для использования подклассами.

confirm_login_allowed(user)

По умолчанию, AuthenticationForm отклоняет пользователей, у которых флаг is_active установлен в False. Вы можете изменить это поведение с помощью пользовательской политики, определяющей, какие пользователи могут войти. Сделайте это с помощью пользовательской формы, которая наследуется от AuthenticationForm и переопределяет метод confirm_login_allowed(). Этот метод должен вызывать ValidationError, если данный пользователь не может войти.

Например, чтобы разрешить вход всем пользователям независимо от статуса «активный»:

from django.contrib.auth.forms import AuthenticationForm

class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
    def confirm_login_allowed(self, user):
        pass

(В этом случае вам также нужно использовать аутентификационный бэкенд, который допускает неактивных пользователей, такой как AllowAllUsersModelBackend.)

Или чтобы разрешить вход только некоторым активным пользователям:

class PickyAuthenticationForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise forms.ValidationError(
                _("This account is inactive."),
                code='inactive',
            )
        if user.username.startswith('b'):
            raise forms.ValidationError(
                _("Sorry, accounts starting with 'b' aren't welcome here."),
                code='no_b_users',
            )
class PasswordChangeForm

Форма для изменения пароля пользователем.

class PasswordResetForm

Форма для генерации и отправки по электронной почте ссылки одноразового использования для сброса пароля пользователя.

send_mail(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)

Использует аргументы для отправки EmailMultiAlternatives. Может быть переопределён для настройки способа отправки письма пользователю.

Параметры:
  • subject_template_name – шаблон для темы.
  • email_template_name – шаблон для тела письма.
  • context – контекст, передаваемый в subject_template, email_template, и html_email_template (если он не None).
  • from_email – адрес отправителя.
  • to_email – адрес получателя.
  • html_email_template_name – шаблон для HTML тела; по умолчанию — None, в этом случае отправляется текстовое письмо.

По умолчанию, save() заполняет context теми же переменными, что и PasswordResetView передаёт в свой контекст электронной почты.

class SetPasswordForm

Форма, позволяющая пользователю изменить пароль без ввода старого пароля.

class UserChangeForm

Форма, используемая в админском интерфейсе для изменения информации и разрешений пользователя.

class UserCreationForm

ModelForm для создания нового пользователя.

Она имеет три поля: username (из модели пользователя), password1, и password2. Она проверяет соответствие password1 и password2, валидирует пароль с помощью validate_password() и устанавливает пароль пользователя с помощью set_password().

Данные аутентификации в шаблонах

Текущий вошедший в систему пользователь и его разрешения доступны в контексте шаблона, когда вы используете RequestContext.

Технические детали

Технически, эти переменные доступны только в контексте шаблона, если вы используете RequestContext и включён процессор контекста 'django.contrib.auth.context_processors.auth'. Он есть в стандартном сгенерированном файле настроек. Более подробная информация в документации RequestContext.

Пользователи

При отрисовке шаблона с помощью RequestContext, текущий вошедший в систему пользователь, либо экземпляр User, либо экземпляр AnonymousUser, хранится в переменной шаблона {{ user }}:

{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
    <p>Welcome, new user. Please log in.</p>
{% endif %}

Эта переменная контекста шаблона недоступна, если RequestContext не используется.

Разрешения

Разрешения текущего вошедшего в систему пользователя хранятся в переменной шаблона {{ perms }}. Это экземпляр django.contrib.auth.context_processors.PermWrapper, который является шаблонно-дружественным прокси-сервером разрешений.

Оценивание одноатрибутного поиска {{ perms }} в качестве булевого значения является прокси для User.has_module_perms(). Например, чтобы проверить, имеет ли вошедший пользователь какие-либо разрешения в приложении foo:

{% if perms.foo %}

Оценивание поиска двух уровневого атрибута в качестве булевого значения является прокси для User.has_perm(). Например, чтобы проверить, имеет ли вошедший пользователь разрешение foo.can_vote:

{% if perms.foo.can_vote %}

Вот более полный пример проверки разрешений в шаблоне:

{% 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 %}

Также можно искать разрешения с помощью {% if in %} выражений. Например:

{% if 'foo' in perms %}
    {% if 'foo.can_vote' in perms %}
        <p>In lookup works, too.</p>
    {% endif %}
{% endif %}

Управление пользователями в админке

При установленных django.contrib.admin и django.contrib.auth, админка предоставляет удобный способ просматривать и управлять пользователями, группами и разрешениями. Пользователей можно создавать и удалять как любые модели Django. Группы можно создавать, а разрешения назначаются пользователям или группам. Также сохраняется и отображается журнал изменений пользователя в моделях, сделанных в админке.

Создание пользователей

Вы должны увидеть ссылку на «Пользователи» в разделе «Auth» на главной странице админки. Страница админки «Добавить пользователя» отличается от стандартных страниц админки тем, что требует выбора имени пользователя и пароля, прежде чем разрешить редактирование остальных полей пользователя.

Также обратите внимание: если вы хотите, чтобы учетная запись пользователя могла создавать пользователей с помощью сайта админки Django, необходимо предоставить им разрешение на добавление пользователей и изменение пользователей (т.е. разрешения «Добавить пользователя» и «Изменить пользователя»). Если у учетной записи есть разрешение на добавление пользователей, но не на изменение, эта учетная запись не сможет добавлять пользователей. Почему? Потому что если у вас есть разрешение на добавление пользователей, вы получаете возможность создавать суперпользователей, которые, в свою очередь, могут изменять других пользователей. Поэтому Django требует разрешений на добавление и изменение как небольшую меру безопасности.

Внимательно отнеситесь к тому, как вы позволяете пользователям управлять разрешениями. Если вы дадите не суперпользователю возможность редактировать пользователей, это в конечном итоге равносильно предоставлению им статуса суперпользователя, поскольку они смогут повышать разрешения пользователей, включая себя!

Изменение паролей

Пароли пользователей не отображаются в админке (и не хранятся в базе данных), но отображаются подробности хранения паролей. В отображении этой информации содержится ссылка на форму изменения пароля, которая позволяет администраторам изменять пароли пользователей.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.1/topics/auth/default/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API